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

SQL中合并重叠与连续日期范围(不使用master..spt_values)

合并重叠/连续日期范围的SQL解决方案

假设你的原始表名为date_ranges,包含字段startdate(起始日期)和enddate(结束日期),如果有分组维度(比如用户IDuser_id),方案也可以适配。

核心思路

利用窗口函数标记出所有重叠或连续的日期区间为同一组,再按组聚合得到合并后的日期范围:

  1. 用LAG()获取上一条记录的结束日期,判断当前区间是否与上一个区间重叠/连续
  2. 通过累加标记生成分组ID
  3. 按分组ID聚合,取每组的最小起始日期和最大结束日期

无分组维度的SQL实现

WITH grouped_ranges AS (
    SELECT
        startdate,
        enddate,
        -- 标记当前区间是否与上一个区间断开:如果当前startdate > 上一个enddate+1,则视为新组
        SUM(CASE WHEN startdate > DATEADD(day, 1, LAG(enddate) OVER (ORDER BY startdate)) THEN 1 ELSE 0 END) 
        OVER (ORDER BY startdate) AS group_id
    FROM date_ranges
)
SELECT
    MIN(startdate) AS merged_startdate,
    MAX(enddate) AS merged_enddate
FROM grouped_ranges
GROUP BY group_id
ORDER BY merged_startdate;

带分组维度的SQL实现(如按用户ID分组)

如果你的数据是按某维度分组(比如每个用户的日期范围),只需在窗口函数中加入PARTITION BY:

WITH grouped_ranges AS (
    SELECT
        user_id,
        startdate,
        enddate,
        SUM(CASE WHEN startdate > DATEADD(day, 1, LAG(enddate) OVER (PARTITION BY user_id ORDER BY startdate)) THEN 1 ELSE 0 END) 
        OVER (PARTITION BY user_id ORDER BY startdate) AS group_id
    FROM date_ranges
)
SELECT
    user_id,
    MIN(startdate) AS merged_startdate,
    MAX(enddate) AS merged_enddate
FROM grouped_ranges
GROUP BY user_id, group_id
ORDER BY user_id, merged_startdate;

说明

  • DATEADD(day, 1, LAG(enddate))是为了处理连续日期(比如上一个区间结束于2023-01-05,当前区间开始于2023-01-06,视为连续需要合并)
  • 如果只需要合并重叠日期,不需要合并连续的,把判断条件改成startdate > LAG(enddate) OVER (...)即可

内容的提问来源于stack exchange,提问作者PRI

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 05:21:30