如何将SQL中的日期范围与小间隙结合起来

如何将SQL中的日期范围与小间隙结合起来,sql,sql-server,data-management,Sql,Sql Server,Data Management,我有一个数据集,其中每一行都有一个日期范围。如果记录重叠,或者间隔不到30天,并且共享相同的ID号,我希望将记录合并到单个日期范围中。如果超过30天,我希望他们分开。如果它们是重叠的,我可以想出如何去做,我可以想出如何去做,不管差距有多大,但我不能想出如何在有限的差距允许下去做 例如,如果我的数据如下所示: ID Date1 Date2 ABC 2018-01-01 2018-02-14 ABC 2018-02-13

我有一个数据集,其中每一行都有一个日期范围。如果记录重叠,或者间隔不到30天,并且共享相同的ID号,我希望将记录合并到单个日期范围中。如果超过30天,我希望他们分开。如果它们是重叠的,我可以想出如何去做,我可以想出如何去做,不管差距有多大,但我不能想出如何在有限的差距允许下去做

例如,如果我的数据如下所示:

ID        Date1           Date2
ABC       2018-01-01      2018-02-14
ABC       2018-02-13      2018-03-17
ABC       2018-04-01      2018-07-24
DEF       2017-01-01      2017-06-30
DEF       2017-10-01      2017-12-01
ID        Date1           Date2
ABC       2018-01-01      2018-07-24
DEF       2017-01-01      2017-06-30
DEF       2017-10-01      2017-12-01
我希望它是这样的:

ID        Date1           Date2
ABC       2018-01-01      2018-02-14
ABC       2018-02-13      2018-03-17
ABC       2018-04-01      2018-07-24
DEF       2017-01-01      2017-06-30
DEF       2017-10-01      2017-12-01
ID        Date1           Date2
ABC       2018-01-01      2018-07-24
DEF       2017-01-01      2017-06-30
DEF       2017-10-01      2017-12-01
ABC的三个日期范围合并在一起,因为它们要么重叠,要么间隔小于30天。DEF的两个日期范围保持分开,因为它们之间的间隔大于30天


我正在使用Microsoft SSMS。

您可以确定新时期从何处开始。对于一般的问题,我认为不存在。然后,您可以使用累积和分配组:

select id, sum(is_start) over (partition by id order by datestart) as grp
from (select t.*,
             (case when not exists (select 1
                                    from t t2
                                    where t2.id = t.id and
                                          t2.date1 >= dateadd(day, -30, t1.date1) and
                                          t2.date2 < dateadd(day, 30, t1.date2)
                                   )
                   then 1 else 0
              end) as is_start
      from t
     ) t;
最后一步是聚合:

with g as (
      select id, sum(is_start) over (partition by id order by datestart) as grp
      from (select t.*,
                   (case when not exists (select 1
                                          from t t2
                                          where t2.id = t.id and
                                                t2.date1 >= dateadd(day, -30, t1.date1) and
                                                t2.date2 < dateadd(day, 30, t1.date2)
                                         )
                         then 1 else 0
                    end) as is_start
            from t
           ) t
      )
select id, min(date1), max(date2)
from g
group by id, grp;

你能分享你在两个场景中的代码吗?对其中一个稍微调整一下就可以了。谢谢!经过几次调整,我能够使它与我的数据集完美结合。