You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 01:15:00