2012-12-05 186 views
1

考虑到以下一组数据,我试图确定如何选择组合日期范围的开始和结束日期,当它们相互交叉时。查找多组日期之间的最小和最大日期

例如,对于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

example-data

编辑: 我目前正在与下面的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 

以下是编辑显示的查询结果:

results from inline query

回答

2

你最好有一个持久的日历表,但如果你不这样做,下面的意志CTE特别创建它。 TOP(36000)部分足以让您在同一行上获得10年的日期('20100101')。

SQL Fiddle

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 | 
+0

谢谢你的详细解答。我会试一试。 – acedanger

+1

@RichardTheKiwi:我刚刚遇到你用T-SQL编写的扫雷码,现在只是我的心灵爆发,而下一刻我看到你的回答这个问题太简单了。 – praveen

+0

@Praveen感谢您的赞扬:) – RichardTheKiwi