SQL Server分隔重叠日期

Con*_*der 0 sql t-sql database sql-server

我有一个包含以下数据的表:

在此输入图像描述

如果类型的日期重叠,我想为重叠期间返回一个单独的行,最后得到以下结果:

在此输入图像描述

Dam*_*ver 6

我现在无视PKey,因为我不确定它是否与问题有关.

这解决了这个问题:

declare @t table (PKey int,Start date,[End] date,Type char(1))
insert into @t(PKey,Start,[End],Type) values
(1,'20100101','20100114','S'),
(2,'20100110','20100131','S'),
(3,'20100105','20100130','A'),
(4,'20100124','20100206','A'),
(5,'20100120','20100127','T'),
(6,'20100128','20100130','T')

;With EndDates as (
    select [End],Type from @t
    union all
    select DATEADD(day,-1,Start),Type from @t
), Periods as (
    select Type,MIN(Start) as Start,
                (select MIN([End]) from EndDates e
                 where e.Type = t.Type and
                 e.[End] >= MIN(Start)) as [End]
    from
        @t t
    group by Type
    union all
    select p.Type,DATEADD(day,1,p.[End]),e.[End]
    from
        Periods p
            inner join
        EndDates e
            on
                p.Type = e.Type and
                p.[End] < e.[End]
    where
        not exists (select * from EndDates e2 where
                e2.Type = p.Type and
                e2.[End] > p.[End] and
                e2.[End] < e.[End])
)
select * from Periods
order by Type,Start
Run Code Online (Sandbox Code Playgroud)

首先,我们创建一个名为CTE EndDates,其中包含可能是期间结束的所有日期 - 这些日期是我们数据中已有的结束日期,或者它们是我们数据中某个开始日期之前的日期.

然后我们建立期间 - 首先我们找到任何特定类型的第一个期间 - 我们采用最早的开始日期,以及开始日期之后的最早可能的结束日期.

然后,递归地,我们通过在现有结束后的第二天开始新的周期来建立额外的周期,并找到该日期之后的最早结束日期.

然后,基本上,我们已经完成了.结果:

Type Start      End
---- ---------- ----------
A    2010-01-05 2010-01-23
A    2010-01-24 2010-01-30
A    2010-01-31 2010-02-06
S    2010-01-01 2010-01-09
S    2010-01-10 2010-01-14
S    2010-01-15 2010-01-31
T    2010-01-20 2010-01-27
T    2010-01-28 2010-01-30
Run Code Online (Sandbox Code Playgroud)

哪个与你问题中的内容不完全匹配,但我认为A2月30日结束的行是一个错字.

(我建议重命名你的End专栏,因为使用专栏的保留字会变成真正的痛苦)