如何将 SQL 中的日期范围与小间隙相结合
How to combine date ranges in SQL with small gaps
我有一个数据集,其中每一行都有一个日期范围。如果记录重叠或间隔少于 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。
您可以确定新月经的开始位置。对于一般问题,我会选择 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;
我有一个数据集,其中每一行都有一个日期范围。如果记录重叠或间隔少于 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。
您可以确定新月经的开始位置。对于一般问题,我会选择 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;