如何合并DB2时态表中business_time相邻的重复行?
合并DB2时态表中相邻时段的重复行解决方案
嘿,针对你要合并DB2时态表里那些id、local_unit、vehicle完全相同,且business_time时段首尾相邻的行的需求,我整理了一个适合批处理场景的方案——既然你说性能不用考虑,咱们就用逻辑清晰的方法来实现,还能处理多行连续相邻的情况,非相邻的行绝对不会被误合并。
核心思路
我们需要先把那些连续相邻的行归为同一个组:对于同一组字段值的行,如果前一行的end正好等于后一行的start,就把它们划到一组。然后对每个组取最早的start和最晚的end,得到合并后的行,最后用这些合并行替换原表中的零散行。
具体SQL代码实现
-- 1. 用递归CTE给连续相邻的行标记组ID WITH grouped_records AS ( -- 初始化:给每个字段组内的行按时间排序,第一行组ID为1 SELECT id, local_unit, vehicle, start, "end", -- 注意end是关键字,需要用引号转义 ROW_NUMBER() OVER (PARTITION BY id, local_unit, vehicle ORDER BY start) AS row_num, 1 AS group_id FROM your_temporal_table UNION ALL -- 递归遍历:如果当前行和上一行时段相邻且字段相同,组ID不变,否则组ID+1 SELECT curr.id, curr.local_unit, curr.vehicle, curr.start, curr."end", curr.row_num, CASE WHEN prev."end" = curr.start THEN prev.group_id ELSE prev.group_id + 1 END AS group_id FROM grouped_records curr JOIN grouped_records prev ON curr.id = prev.id AND curr.local_unit = prev.local_unit AND curr.vehicle = prev.vehicle AND curr.row_num = prev.row_num + 1 ), -- 2. 按组聚合,得到合并后的行 merged_results AS ( SELECT id, local_unit, vehicle, MIN(start) AS start, MAX("end") AS "end" FROM grouped_records GROUP BY id, local_unit, vehicle, group_id ) -- 3. 用MERGE语句更新原表:插入合并行,删除原有的零散行 MERGE INTO your_temporal_table tgt USING merged_results src ON tgt.id = src.id AND tgt.local_unit = src.local_unit AND tgt.vehicle = src.vehicle AND tgt.start = src.start AND tgt."end" = src."end" WHEN NOT MATCHED THEN -- 插入合并后的行,同时设置business_time时段 INSERT (id, local_unit, vehicle, start, "end", business_time) VALUES (src.id, src.local_unit, src.vehicle, src.start, src."end", PERIOD(src.start, src."end")) WHEN MATCHED THEN -- 删除原有的未合并行 DELETE;
关键细节说明
- 记得把
your_temporal_table替换成你实际的表名 - 因为
end是DB2的关键字,所以在SQL里用双引号转义了,避免语法错误 - 递归CTE会自动处理多行连续相邻的情况(比如3行甚至更多行首尾相连的场景),非相邻的行会被分到不同的组,不会被合并
- 时态表的
business_time字段需要和start、end对应,所以插入时明确用PERIOD(start, end)来设置这个字段的值 - 这个方案是批处理友好的,不用考虑性能问题,逻辑清晰易懂,方便你后续维护
内容的提问来源于stack exchange,提问作者Stefan F
相关产品推荐
相关产品推荐

