鉴于以下数据集,我试图确定如何在组合日期范围相互交叉时选择开始日期和结束日期。
例如,对于PartNum 115678,我希望我的最终结果集显示日期范围2012/01/01 - 2012/01/19
(自日期范围相交以来合并的第1,2和4行)和2012/02/01 - 2012/03/28
(第3行)因为这个与之前找到的范围不相交)。
对于PartNum 213275,我想要选择该部分的唯一行2012/12/01 - 2013/01/01
。
编辑: 我目前正在使用以下SQL语句,但它并没有完全满足我的需要。
with DistinctRanges as (
select distinct
ha1.PartNum "PartNum",
ha1.StartDt "StartDt",
ha2.EndDt "EndDt"
from dbo.HoldsAll ha1
inner join dbo.HoldsAll ha2
on ha1.PartNum = ha2.PartNum
where
ha1.StartDt <= ha2.EndDt
and ha2.StartDt <= ha1.EndDt
)
select
PartNum,
StartDt,
EndDt
from DistinctRanges
以下是编辑中显示的查询结果:
答案 0 :(得分:2)
你最好拥有一个持久化的Calendar表,但是如果你不这样做,下面的CTE将会临时创建它。 TOP(36000)
部分足以在同一行的枢轴('20100101'
)上为您提供10年的日期。
MS SQL Server 2008架构设置:
create table data (
partnum int,
startdt datetime,
enddt datetime,
age int
);
insert data select
12345, '20120101', '20120116', 15 union all select
12345, '20120115', '20120116', 1 union all select
12345, '20120201', '20120328', 56 union all select
12345, '20120113', '20120119', 6 union all select
88872, '20120201', '20130113', 43;
查询1 :
with Calendar(thedate) as (
select TOP(36600) dateadd(d,row_number() over (order by 1/0),'20100101')
from sys.columns a
cross join sys.columns b
cross join sys.columns c
), tmp as (
select partnum, thedate,
grouper = datediff(d, dense_rank() over (partition by partnum order by thedate), thedate)
from Calendar c
join data d on d.startdt <= c.thedate and c.thedate <= d.enddt
)
select partnum, min(thedate) startdt, max(thedate) enddt
from tmp
group by partnum, grouper
order by partnum, startdt
<强> Results 强>:
| PARTNUM | STARTDT | ENDDT |
------------------------------------------------------------------------------
| 12345 | January, 01 2012 00:00:00+0000 | January, 19 2012 00:00:00+0000 |
| 12345 | February, 01 2012 00:00:00+0000 | March, 28 2012 00:00:00+0000 |
| 88872 | February, 01 2012 00:00:00+0000 | January, 13 2013 00:00:00+0000 |