【问题标题】:How to combine date ranges in SQL with small gaps如何在 SQL 中将日期范围与小间隔结合起来
【发布时间】:2018-08-20 16:11:09
【问题描述】:

我有一个数据集,其中每一行都有一个日期范围。如果记录重叠或间隔小于 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

ABC 的三个日期范围合并在一起,因为它们要么重叠,要么间隔小于 30 天。 DEF 的两个日期范围保持独立,因为它们之间的间隔大于 30 天。

我正在使用 Microsoft SSMS。

【问题讨论】:

  • 你能分享一下你工作的两个场景的代码吗?对其中一个进行轻微调整即可为您做到这一点。

标签: sql sql-server data-management


【解决方案1】:

您可以确定新时期的开始位置。对于一般问题,我会选择not exists。然后您可以使用累积和分配一个组:

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;

【讨论】:

  • 谢谢!通过一些调整,我能够让它与我的数据集完美配合。
猜你喜欢
  • 1970-01-01
  • 2017-04-06
  • 2014-08-23
  • 2017-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多