如何在SQL Server中按日期范围分区数据并获取目标输出
在SQL Server中合并重叠/连续日期区间
我们需要按ID对记录分组,将同一ID下重叠或连续的日期区间合并,保留该区间的最早开始日期和最晚结束日期;非重叠的区间则保持原样。
输入数据
| ID | Start_Date | End_Date |
|---|---|---|
| 1 | 2022-01-01 | 2022-03-31 |
| 1 | 2022-02-15 | 2022-04-15 |
| 1 | 2022-02-01 | 2022-03-31 |
| 1 | 2022-11-02 | 2022-11-06 |
| 1 | 2022-11-20 | 2022-11-23 |
目标输出
| ID | Start_Date | End_Date |
|---|---|---|
| 1 | 2022-01-01 | 2022-04-15 |
| 1 | 2022-11-02 | 2022-11-06 |
| 1 | 2022-11-20 | 2022-11-23 |
解决方案
可以通过**窗口函数+CTE(公共表表达式)**实现需求,核心是给每个重叠/连续的区间分配同一个分组ID,再按分组聚合计算最小开始日期和最大结束日期。
完整SQL代码:
WITH RankedDates AS ( SELECT ID, Start_Date, End_Date, -- 标记分组:当前记录的Start_Date > 之前所有记录的最大End_Date时,生成新分组 SUM(CASE WHEN Start_Date <= LAG(Max_End_Date, 1, '1900-01-01') OVER (PARTITION BY ID ORDER BY Start_Date) THEN 0 ELSE 1 END) OVER (PARTITION BY ID ORDER BY Start_Date) AS GroupID FROM ( -- 先按ID和Start_Date排序,计算到当前行为止的最大End_Date SELECT ID, Start_Date, End_Date, MAX(End_Date) OVER (PARTITION BY ID ORDER BY Start_Date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Max_End_Date FROM YourTableName ) t ) SELECT ID, MIN(Start_Date) AS Start_Date, MAX(End_Date) AS End_Date FROM RankedDates GROUP BY ID, GroupID ORDER BY ID, Start_Date;
代码说明
- 内层子查询:按ID分组、Start_Date排序,计算到当前记录为止的最大End_Date,用于判断后续记录是否和前面的区间重叠。
- 外层CTE:使用
LAG函数获取上一个分组的最大End_Date,判断当前记录的Start_Date是否在该范围内,生成分组ID。如果当前Start_Date大于上一个分组的最大End_Date,则创建新分组。 - 最终聚合:按ID和GroupID分组,取每个分组的最小Start_Date和最大End_Date,得到合并后的结果。
注意:将YourTableName替换为你的实际表名。
内容的提问来源于stack exchange,提问作者P Kernel
相关产品推荐
相关产品推荐

