DB2数据库中计算用户去重重叠任务时段的有效工作总时长
DB2数据库中计算用户去重重叠任务时段的有效工作总时长
我完全懂你的烦恼——当用户同时处理多个任务时,直接把每个任务的时长加起来,重叠的时间会被重复计算,结果自然和实际的有效工作时长不符。针对DB2的场景,我们可以用**公共表表达式(CTE)**结合时段合并的思路来解决这个问题,核心就是把每个用户的重叠/连续任务时段合并成不重叠的完整时段,再计算总时长。
解决思路
- 先给每个用户的任务按开始时间排序,用窗口函数识别哪些时段是重叠或连续的,给它们打上同一个分组标记
- 按用户和分组标记聚合,把同一组的重叠时段合并成一个完整的时间段(取最早的开始时间和最晚的结束时间)
- 对每个用户的合并后时段计算总时长,格式化成你需要的
HH:MI:SS格式
具体SQL代码
WITH task_intervals AS ( SELECT Userid, Start_datetime, End_datetime, -- 生成不重叠时段的分组ID:如果当前任务开始时间早于上一个任务的结束时间,属于同一组 SUM(CASE WHEN Start_datetime <= LAG(End_datetime) OVER (PARTITION BY Userid ORDER BY Start_datetime) THEN 0 ELSE 1 END) OVER (PARTITION BY Userid ORDER BY Start_datetime) AS interval_group FROM your_table_name -- 替换成你的实际表名 ), merged_intervals AS ( SELECT Userid, MIN(Start_datetime) AS merged_start, MAX(End_datetime) AS merged_end FROM task_intervals GROUP BY Userid, interval_group ) SELECT Userid, -- 计算合并后时段的总时长,并格式化为HH:MI:SS VARCHAR_FORMAT( SUM( DAYS_BETWEEN(merged_end, merged_start) * 86400 + SECOND(merged_end - merged_start) ), 'HH24:MI:SS' ) AS "Total Time" FROM merged_intervals GROUP BY Userid ORDER BY Userid;
代码解释
task_intervalsCTE:- 用
LAG(End_datetime) OVER (...)获取当前用户上一个任务的结束时间 - 通过CASE判断当前任务是否和上一个任务重叠:如果当前任务开始时间≤上一个任务结束时间,说明重叠,属于同一组(加0);否则新建一个组(加1)
- 用
SUM OVER累加分组标记,得到每个时段的分组ID
- 用
merged_intervalsCTE:- 按用户和分组ID聚合,把同一组的重叠/连续时段合并成一个完整的时间段——取该组最早的开始时间和最晚的结束时间
最终查询:
- 计算每个合并后时段的秒数:天数差转成秒(1天=86400秒)加上时分秒的秒数
- 用
VARCHAR_FORMAT把总秒数转成HH24:MI:SS的格式,得到每个用户的有效工作总时长
验证你的示例数据
用你提供的数据测试的话:
- User2:Task1和Task2合并为
08:30-11:30(3小时),Task3和第二个Task1重叠合并为15:15-16:00(45分),总时长03:45:00,和你的期望结果完全一致。 - User1:Task1和Task2重叠合并为
08:00-10:00(2小时),加上Task3的11:15-13:00(1小时45分),总时长03:45:00——这里和你标注的期望结果有差异,应该是你提供的Task3时长标注有误,但代码会严格根据Start_datetime和End_datetime计算,确保结果准确。
注意事项
- 记得把代码里的
your_table_name替换成你实际的表名 - 确保
Start_datetime和End_datetime是DB2的TIMESTAMP类型,如果是字符串类型,需要先用TIMESTAMP()函数转换 - 如果你的DB2版本支持
TIMESTAMPDIFF函数,也可以用它来简化时长计算,但上面的方法兼容性更好
备注:内容来源于stack exchange,提问作者morenen
相关产品推荐
相关产品推荐

