1

我仍然是我的英语的新手和借口。您会看到我有两个不同时期的人,如果他们是连续的,我想聚合这些时期。我不知道如何使用例如与下一行或前一行相关的min()and函数来比较日期。max()还是有更简单的方法来解决这个问题?我只有没有滞后和领先功能的 SQL Server 2008 R2。

样本数据:

DECLARE @Table TABLE( 
    PersonID INT, 
    FROM    date, 
    TO date 
)

INSERT INTO @Table SELECT 1,'2011-01-01','2011-04-30'
INSERT INTO @Table SELECT 1,'2011-05-01','2011-08-31'
INSERT INTO @Table SELECT 1,'2011-09-01','2011-12-31'
INSERT INTO @Table SELECT 1,'2012-01-01','2012-03-31'

INSERT INTO @Table SELECT 2,'2011-03-01','2011-06-30'
INSERT INTO @Table SELECT 2,'2011-07-01','2011-10-31'
INSERT INTO @Table SELECT 2,'2013-01-01','2013-04-30'
INSERT INTO @Table SELECT 2,'2013-05-01','2013-08-31'

我期待这样的事情,尤其是在 PersonID 2 上:

 PersonID FROM TO 
 1 , 2011-01-01 , 2012-03-31
 2 , 2011-03-01 , 2011-10-31
 2 , 2013-01-01 , 2013-08-31
4

1 回答 1

1

这是一个很难解决的问题,使用累积和lag()或会变得更容易lead()。你仍然可以做这项工作。我更喜欢使用相关子查询来表达它。

该逻辑首先确定哪些记录通过重叠连接到“下一个”记录。以下查询使用此逻辑来定义OverlapWithPrev.

      select *
      from (select t.*,
                   (select top 1 1
                    from t t2
                    where t2.personid = t.personid and
                          t2.fromd < t.fromd and
                          t2.tod >= dateadd(d, -1, t.fromd)
                    order by t2.fromd
                   ) as OverlapWithPrev
            from t
           ) t

1具有先前记录和NULL没有记录时的值。

然后使用此信息,查询为每条记录查找不与前一条重叠的下一条记录(并且在同一个人上)。当你有一系列重叠的记录时,那么所有的记录都会有相同的下一条记录,并且下一条记录用于聚合。

这是完整的查询:

with tp as 
     (select *
      from (select t.*,
                   (select top 1 1
                    from t t2
                    where t2.personid = t.personid and
                          t2.fromd < t.fromd and
                          t2.tod >= dateadd(d, -1, t.fromd)
                    order by t2.fromd
                   ) as OverlapWithPrev
            from t
           ) t
     )
select personid, min(fromd) as fromd, max(tod) as tod
from (select tp.*,
             (select top 1 fromd
              from tp tp2
              where tp2.OverlapWithPrev is null and
                    tp2.personid = tp.personid and
                    tp2.fromd > tp.fromd
             ) as NextFromD
      from tp
     ) tp
group by personid, NextFromD;

是一个 SQLFiddle 来展示它是如何工作的。

于 2013-06-16T19:49:27.420 回答