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

SQL Server中合并重叠日期时间区间的技术实现问题

解决重叠/首尾相接时间区间合并问题

你的问题核心在于原方案仅基于**日期(天)**处理区间,完全忽略了datetime中的时间部分,导致时间维度的重叠或首尾相接场景无法正确合并,而且依赖Numbers表的方法在处理长区间时效率也偏低。

推荐解决方案:使用窗口函数的区间合并方法

不需要依赖额外的Numbers表,直接通过窗口函数标记并合并区间,能完美处理时间部分和首尾相接的情况:

WITH CTE_IntervalFlags AS (
    SELECT 
        Name,
        Datetime_Start,
        Datetime_End,
        -- 判断当前区间是否需要开启新分组:如果当前区间的开始时间 <= 前一个区间的结束时间(含首尾相接),则归为同一组
        CASE 
            WHEN Datetime_Start <= LAG(Datetime_End) OVER (PARTITION BY Name ORDER BY Datetime_Start)
            THEN 0
            ELSE 1
        END AS IsNewGroup
    FROM Mytable
),
CTE_GroupedIntervals AS (
    SELECT 
        Name,
        Datetime_Start,
        Datetime_End,
        -- 累计求和生成组ID,同一连续区间的组ID相同
        SUM(IsNewGroup) OVER (
            PARTITION BY Name 
            ORDER BY Datetime_Start 
            ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
        ) AS IntervalGroupID
    FROM CTE_IntervalFlags
)
SELECT 
    Name,
    MIN(Datetime_Start) AS Datetime_Start,
    MAX(Datetime_End) AS Datetime_End
FROM CTE_GroupedIntervals
GROUP BY Name, IntervalGroupID
ORDER BY Name, Datetime_Start;

方案说明

  1. 标记新组:通过LAG()窗口函数获取当前Name下前一个区间的结束时间,判断当前区间是否与前一个区间重叠或首尾相接,标记是否为新组。
  2. 生成组ID:对标记的新组标识做累计求和,同一连续的重叠/相接区间会得到相同的组ID。
  3. 合并区间:按Name和组ID分组,取组内最小的开始时间和最大的结束时间,得到合并后的结果。

原方案问题分析

你原用的Numbers表方法仅按天生成时间点,存在两个关键问题:

  • 对于同一天内的时间重叠区间(比如B的两个区间),生成的NewStartDate会是不同的时间点,导致DENSE_RANK计算出不同的分组值,无法合并。
  • 对于跨天但时间首尾相接的区间,也会因为日期分组的逻辑错误,无法识别为连续区间。

这个窗口函数方案不仅更高效,还能精准处理datetime的全维度时间信息,完美匹配你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:23:27