请求实现按Name合并重叠时间区间的数据行
分组合并重叠时间区间的实现方案
问题描述
按Name分组,合并每组内所有重叠的时间区间:合并后行的Start Time取区间最小值,End Time取区间最大值;无重叠区间保留原行。
原始数据表
| Name | Start Time | End Time |
|---|---|---|
| Name C | 4/1/2025 5:00 AM | 4/2/2025 3:50 PM |
| Name A | 1/3/2025 1:00 PM | 1/10/2025 1:00 PM |
| Name A | 1/5/2025 1:00 PM | 1/20/2025 5:00 PM |
| Name A | 3/2/2025 1:00 PM | 3/8/2025 1:00 PM |
| Name B | 2/2/2025 2:00 PM | 2/5/2025 3:00 PM |
| Name C | 1/15/2025 1:30 PM | 1/19/2025 3:45 PM |
| Name C | 1/12/2025 9:00 AM | 1/20/2025 1:00 AM |
| Name D | 1/2/2025 10:00 AM | 1/2/2025 1:00 PM |
| Name A | 1/1/2025 5:00 AM | 1/15/2025 3:00 PM |
| Name D | 1/2/2025 11:00 AM | 1/4/2025 3:00 PM |
期望结果表
| Name | Start Time | End Time |
|---|---|---|
| Name A | 1/1/2025 5:00 AM | 1/20/2025 5:00 PM |
| Name A | 3/2/2025 1:00 PM | 3/8/2025 1:00 PM |
| Name B | 2/2/2025 2:00 PM | 2/5/2025 3:00 PM |
| Name C | 1/12/2025 9:00 AM | 1/20/2025 1:00 AM |
| Name C | 4/1/2025 5:00 AM | 4/2/2025 3:50 PM |
| Name D | 1/2/2025 10:00 AM | 1/4/2025 3:00 PM |
解决方案(标准SQL)
使用窗口函数标记分组内的重叠区间,再聚合合并:
WITH ranked_intervals AS ( SELECT Name, Start_Time, End_Time, -- 标记当前区间是否与前一个区间重叠,生成分组ID SUM(CASE WHEN Start_Time <= LAG(End_Time) OVER (PARTITION BY Name ORDER BY Start_Time) THEN 0 ELSE 1 END) OVER (PARTITION BY Name ORDER BY Start_Time) AS group_id FROM your_table ), merged_intervals AS ( SELECT Name, MIN(Start_Time) AS Start_Time, MAX(End_Time) AS End_Time FROM ranked_intervals GROUP BY Name, group_id ) SELECT * FROM merged_intervals ORDER BY Name, Start_Time;
步骤说明
- 排序并标记分组ID:按
Name分组,每组内按Start Time排序。用LAG函数获取前一个区间的End Time,如果当前区间的Start Time小于等于前一个的End Time,说明重叠,分组ID不变;否则生成新的分组ID。 - 聚合合并区间:按
Name和group_id分组,取每组的最小Start Time和最大End Time,得到合并后的区间。 - 排序输出:按
Name和Start Time排序,输出结果与期望一致。
结果验证
执行上述SQL后将得到符合期望的输出:
- Name A的三个1月区间重叠,合并为一个;3月区间独立保留。
- Name C的两个1月区间重叠,合并为一个;4月区间独立保留。
- Name D的两个区间重叠,合并为一个。
- Name B仅一个区间,直接保留。
内容的提问来源于stack exchange,提问作者UBP
相关产品推荐
相关产品推荐

