查找多组日期之间的最小和最大日期

时间:2012-12-05 01:12:25

标签: sql-server date-range

鉴于以下数据集,我试图确定如何在组合日期范围相互交叉时选择开始日期和结束日期。

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

1 个答案:

答案 0 :(得分:2)

你最好拥有一个持久化的Calendar表,但是如果你不这样做,下面的CTE将会临时创建它。 TOP(36000)部分足以在同一行的枢轴('20100101')上为您提供10年的日期。

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 |