如何仅用SQL合并连续时间跨度?无需函数或存储过程
合并连续时间跨度的SQL实现方案
针对你提出的合并连续时间区间的需求,这里提供一个纯SQL的实现方案,无需自定义函数或存储过程,适用于支持窗口函数的主流数据库(如MySQL 8.0+、PostgreSQL、SQL Server等):
实现思路
核心是通过窗口函数给每个连续的时间区间分配唯一分组ID,再按分组聚合得到合并后的区间:
- 标记连续区间的起始点:对比当前记录的
FromTime与同ID上一条记录的ThruTime,若不相等则标记为新区间起点 - 累加起始点标记生成分组ID:同属一个连续区间的记录会被分配相同的分组ID
- 按ID和分组ID聚合,取区间的最小起始时间和最大结束时间
具体SQL代码
假设你的表名为time_intervals,执行以下语句:
WITH interval_groups AS ( SELECT ID, FromTime, ThruTime, SUM(CASE WHEN LAG(ThruTime) OVER (PARTITION BY ID ORDER BY FromTime) = FromTime THEN 0 ELSE 1 END) OVER (PARTITION BY ID ORDER BY FromTime) AS group_id FROM time_intervals ) SELECT ID, MIN(FromTime) AS FromTime, MAX(ThruTime) AS ThruTime FROM interval_groups GROUP BY ID, group_id ORDER BY ID, FromTime;
逻辑说明
LAG(ThruTime) OVER (PARTITION BY ID ORDER BY FromTime):按ID分组、时间排序,获取当前记录的上一条记录的结束时间- 用CASE语句判断是否为新区间起点:如果上一条的结束时间不等于当前的起始时间,说明是新区间,标记为1,否则标记为0
SUM() OVER (...):累加标记值,生成连续区间的分组ID,确保同一连续区间的记录拥有相同的group_id- 最后按ID和group_id分组,取最小的
FromTime作为合并后区间的起点,最大的ThruTime作为终点,得到目标结果
执行结果
运行上述SQL后,会得到你需要的合并结果:
| ID | FromTime | ThruTime |
|---|---|---|
| X | 08:00 | 09:30 |
| X | 09:45 | 11:15 |
| X | 11:45 | 12:45 |
内容的提问来源于stack exchange,提问作者Naren Lulla
相关产品推荐
相关产品推荐

