SQL中如何比较同表相邻两条记录的End Date与Start_Date并合并数据
同表相邻时间区间合并SQL实现
我们可以通过窗口函数标记连续区间再聚合的方式实现需求,以下是完整实现逻辑及代码:
核心逻辑说明
- 按
Name字段分组,同组内按Start_Date升序排序,保证时间区间按先后顺序排列 - 用窗口函数获取同组内上一条记录的
End_Date,判断当前区间是否和上一个区间连续(判断规则:当前Start_Date= 上一条End_Date+ 1天) - 给不连续的区间打上新分组标记,连续的区间归属同一个分组
- 按
Name和分组标记聚合,取每个分组最小Start_Date、最大End_Date得到合并后的结果
通用SQL实现(以MySQL 8.0+为例)
假设表名为time_range_tb,字段为Name、Start_Date、End_Date,日期字段为标准日期类型:
WITH step1 AS ( -- 第一步:获取同组上一条记录的End_Date SELECT Name, Start_Date, End_Date, LAG(End_Date, 1) OVER (PARTITION BY Name ORDER BY Start_Date) AS pre_end FROM time_range_tb ), step2 AS ( -- 第二步:标记新区间起点 SELECT Name, Start_Date, End_Date, CASE WHEN Start_Date = DATE_ADD(pre_end, INTERVAL 1 DAY) THEN 0 ELSE 1 END AS new_flag FROM step1 ), step3 AS ( -- 第三步:生成连续区间分组ID SELECT Name, Start_Date, End_Date, SUM(new_flag) OVER (PARTITION BY Name ORDER BY Start_Date) AS group_id FROM step2 ) -- 第四步:聚合得到合并后结果 SELECT Name, MIN(Start_Date) AS merged_start_date, MAX(End_Date) AS merged_end_date FROM step3 GROUP BY Name, group_id ORDER BY Name, merged_start_date;
不同数据库适配说明
- PostgreSQL:日期加1天写法替换为
pre_end + INTERVAL '1 day' - Oracle:日期加1天写法替换为
pre_end + 1,LAG函数语法一致 - 低版本不支持窗口函数的数据库:可通过自关联的方式实现,性能略低于窗口函数方案
效果验证
针对你给出的示例数据,两条Name为ABC的记录执行上述SQL后,会被归属到同一个分组,最终返回合并结果Start_Date = 2020-01-01、End_Date = 2020-05-04,符合需求。
内容的提问来源于stack exchange,提问作者Nev
相关产品推荐
相关产品推荐

