Access 2016:查询合并重叠日期时间记录的方法
合并重叠/连续时间区间的SQL解决方案
这个需求我太熟了,本质就是把重叠或者连续的时间记录合并成完整的区间,取每组最早的开始时间和最晚的结束时间。下面给你一套通用的实现方案,适配大多数主流数据库(MySQL、PostgreSQL、SQL Server都能用)。
核心思路
我们可以通过窗口函数分组的方式来识别哪些记录属于同一个重叠区间:
- 先按时间开始字段排序,用
LAG函数拿到上一条记录的结束时间 - 判断当前记录的开始时间是否小于等于上一条的结束时间——如果是,说明属于同一个区间;否则是新的区间
- 累计这个分组标记,给每个区间分配唯一的
group_id - 最后按
group_id聚合,取每组的最早开始时间和最晚结束时间
完整SQL代码
假设你的表名叫your_table,如果时间字段是字符串类型,先转成日期时间类型再处理:
-- 第一步:格式化时间字符串为日期类型(如果你的字段已经是DATETIME/TIMESTAMP可以跳过这个CTE) WITH formatted_records AS ( SELECT Main_ID, -- 这里根据你的时间格式调整转换函数,示例是DD/MM/YYYY HH:MM:SS STR_TO_DATE(timestart, '%d/%m/%Y %H:%i:%s') AS timestart, STR_TO_DATE(timeend, '%d/%m/%Y %H:%i:%s') AS timeend FROM your_table ), -- 第二步:给每条记录分配分组ID ranked_records AS ( SELECT Main_ID, timestart, timeend, SUM( CASE WHEN timestart <= LAG(timeend) OVER (ORDER BY timestart) THEN 0 ELSE 1 END ) OVER (ORDER BY timestart) AS group_id FROM formatted_records ), -- 第三步:按分组聚合合并区间 merged_intervals AS ( SELECT group_id, MIN(timestart) AS merged_timestart, MAX(timeend) AS merged_timeend FROM ranked_records GROUP BY group_id ) -- 最后输出格式化后的结果 SELECT DATE_FORMAT(merged_timestart, '%d/%m/%Y %H:%i:%s') AS merged_timestart, DATE_FORMAT(merged_timeend, '%d/%m/%Y %H:%i:%s') AS merged_timeend FROM merged_intervals ORDER BY merged_timestart;
针对你的示例数据的结果
运行上面的代码后,你的示例数据会合并成两个区间:
02/10/2014 06:00:00→02/10/2014 17:00:00(合并前3条重叠记录)02/10/2014 18:30:00→04/10/2014 00:00:00(合并40965、40967、40968、40972的重叠区间)
注意事项
- 如果你的数据库不支持CTE(比如MySQL 5.7及以前),可以把CTE替换成子查询
- 确保时间字段的格式和转换函数匹配,比如如果是
MM/DD/YYYY格式,要把%d/%m改成%m/%d - 如果是连续的时间(比如上一条的结束时间等于下一条的开始时间),也会被合并,符合你的需求
内容的提问来源于stack exchange,提问作者EddieL
相关产品推荐
相关产品推荐

