Con*_*der 0 sql t-sql database sql-server
我有一个包含以下数据的表:

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

我现在无视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专栏,因为使用专栏的保留字会变成真正的痛苦)