从日期范围中查找占用日期

时间:2013-08-15 07:13:21

标签: sql sql-server sql-server-2008 tsql sql-server-2005

这是我在SQL-Sever 2005模式下的数据

ID              FromDate    ToDate        Diff

ZIM145876-01    03/01/2011  02/29/2012    1
ZIM145876-01    03/01/2012  02/28/2013    1
ZIM145876-01    03/01/2013  02/28/2014    NULL


ZIM145881-02    02/01/2012  03/31/2012    1
ZIM145881-02    04/01/2012  06/30/2012    1
ZIM145881-02    07/01/2012  09/30/2012    1
ZIM145881-02    10/01/2012  03/31/2013    1
ZIM145881-02    04/01/2013  06/30/2013    NULL


ZIM145878-01    05/15/2010  05/14/2011    201
ZIM145878-01    12/01/2011  11/30/2012    1
ZIM145878-01    12/01/2012  11/30/2013    NULL

现在我想要第一个案例

ZIM145876-01    03/01/2011  02/28/2014

ZIM145881-02    02/01/2012  06/30/2013

然而,在第三种情况下,我们有两个相同ID的占用日期,这就是我想要的

ZIM145878-01    05/15/2010  05/14/2011
ZIM145878-01    12/01/2011  11/30/2013

所以任何暗示都会受到高度赞赏 (SQLFiddle

1 个答案:

答案 0 :(得分:1)

这似乎可以胜任。不幸的是,它在大型数据集上效率不高:

declare @t table (ID varchar(50),FromDate date,ToDate date, Diff int)
insert into @t(ID,FromDate,ToDate,Diff) values
('ZIM145876-01','20110301','20120229',1   ),
('ZIM145876-01','20120301','20130228',1   ),
('ZIM145876-01','20130301','20140228',NULL),
('ZIM145881-02','20120201','20120331',1   ),
('ZIM145881-02','20120401','20120630',1   ),
('ZIM145881-02','20120701','20120930',1   ),
('ZIM145881-02','20121001','20130331',1   ),
('ZIM145881-02','20130401','20130630',NULL),
('ZIM145878-01','20100515','20110514',201 ),
('ZIM145878-01','20111201','20121130',1   ),
('ZIM145878-01','20121201','20131130',NULL)

;With Islands as (
    select ID,FromDate,ToDate from @t t1 where not exists (select * from @t t2 where t2.ToDate = DATEADD(day,-1,t1.FromDate) and t1.ID = t2.ID)
    union all
    select i.ID,i.FromDate,t.ToDate
    from
        Islands i
            inner join
        @t t
            on
                i.ID = t.ID and
                i.ToDate = DATEADD(day,-1,t.FromDate)
)
select ID,FromDate,MAX(ToDate) from Islands
group by ID,FromDate

结果:

ID                                                 FromDate   
-------------------------------------------------- ---------- ----------
ZIM145878-01                                       2010-05-15 2011-05-14
ZIM145876-01                                       2011-03-01 2014-02-28
ZIM145878-01                                       2011-12-01 2013-11-30
ZIM145881-02                                       2012-02-01 2013-06-30

如果占用率被记录为半开放区间(例如Inclusive FromDate,Exclusive ToDate),则可能更有效率 - 因为那样我们就不必致电DATEADD来找到期间加入的地方在一起。

我不知道Diff列的内容是什么,我还没有使用它。