使用SQL按30分钟间隔计算呼叫等待时长(Hold Time)
按30分钟间隔统计呼叫等待时长的SQL优化方案
需求说明
按30分钟时间间隔统计呼叫等待时长(Hold Time,单位为秒),最终需按ID、StartDate、30分钟区间的起止时间汇总holdtime。
输入数据
输入表包含Date、ID、StartDate、StartTime、holdtime字段,示例数据如下:
| Date | ID | StartDate | StartTime | holdtime |
|---|---|---|---|---|
| 28/12/2022 | 3110522 | 28/12/2022 | 10:03:46.0000000 | 62 |
| 28/12/2022 | 3110522 | 28/12/2022 | 10:36:42.0000000 | 189 |
| 28/12/2022 | 3110522 | 28/12/2022 | 11:06:54.0000000 | 65 |
| 28/12/2022 | 3110522 | 28/12/2022 | 11:11:46.0000000 | 79 |
| 28/12/2022 | 3110522 | 28/12/2022 | 11:19:55.0000000 | 118 |
| 28/12/2022 | 3110522 | 28/12/2022 | 11:38:20.0000000 | 36 |
| 28/12/2022 | 3110522 | 28/12/2022 | 12:13:46.0000000 | 67 |
| 28/12/2022 | 3110522 | 28/12/2022 | 13:45:27.0000000 | 24 |
| 28/12/2022 | 3110522 | 28/12/2022 | 13:52:59.0000000 | 144 |
| 28/12/2022 | 3110522 | 28/12/2022 | 15:02:43.0000000 | 39 |
| 28/12/2022 | 3110522 | 28/12/2022 | 16:00:41.0000000 | 246 |
| 28/12/2022 | 3110522 | 28/12/2022 | 16:54:22.0000000 | 79 |
| 28/12/2022 | 3110522 | 28/12/2022 | 16:59:18.0000000 | 94 |
| 28/12/2022 | 3110522 | 28/12/2022 | 17:29:19.0000000 | 84 |
| 28/12/2022 | 3110522 | 28/12/2022 | 17:54:44.0000000 | 64 |
期望输出
按ID、StartDate、30分钟区间起止时间汇总holdtime,示例输出如下:
| ID | StartDate | intervalStartTime | intervalStoptTime | holdtime |
|---|---|---|---|---|
| 3110522 | 28/12/2022 | 10:00:00.000 | 10:30:00.0000000 | 62 |
| 3110522 | 28/12/2022 | 10:30:00.000 | 11:00:00.0000000 | 189 |
| 3110522 | 28/12/2022 | 11:00:00.000 | 11:30:00.0000000 | 262 |
| 3110522 | 28/12/2022 | 11:30:00.000 | 12:00:00.0000000 | 36 |
| 3110522 | 28/12/2022 | 12:00:00.000 | 12:30:00.0000000 | 67 |
| 3110522 | 28/12/2022 | 13:30:00.000 | 14:00:00.0000000 | 168 |
| 3110522 | 28/12/2022 | 15:00:00.000 | 15:30:00.0000000 | 39 |
| 3110522 | 28/12/2022 | 16:00:00.000 | 16:30:00.0000000 | 246 |
| 3110522 | 28/12/2022 | 16:30:00.000 | 17:00:00.0000000 | 121 |
| 3110522 | 28/12/2022 | 17:00:00.000 | 17:30:00.0000000 | 93 |
| 3110522 | 28/12/2022 | 17:30:00.000 | 18:00:00.0000000 | 107 |
现有尝试问题
曾使用WHILE循环实现,但逻辑复杂且未得到预期结果,循环代码如下:
while (@eventDurationMins>0) begin set @eventDurationInIntervalMins = cast(@intervalEndTime-@eventStartTime as float)*24*60 ; if @eventDurationMins<@eventDurationInIntervalMins set @eventDurationInIntervalMins = @eventDurationMins ; insert into @retTable select @intervalStartTime,@intervalEndTime,@eventDurationInIntervalMins set @eventDurationMins = @eventDurationMins - @eventDurationInIntervalMins ; set @eventStartTime = @intervalEndTime; set @intervalStartTime = @intervalEndTime; set @intervalEndTime = dateadd(minute,@intervalMins,@intervalEndTime); end;
优化SQL解决方案
无需循环,通过日期截断的方式将每条记录映射到对应的30分钟区间,再分组求和即可。以下是适用于SQL Server的实现代码:
SELECT ID, StartDate, -- 生成30分钟区间的起始时间,格式匹配示例输出 FORMAT(DATEADD(MINUTE, DATEDIFF(MINUTE, 0, StartTime) / 30 * 30, 0), 'HH:mm:ss.fff') AS intervalStartTime, -- 生成30分钟区间的结束时间,格式匹配示例输出 FORMAT(DATEADD(MINUTE, (DATEDIFF(MINUTE, 0, StartTime) / 30 + 1) * 30, 0), 'HH:mm:ss.fffffff') AS intervalStoptTime, SUM(holdtime) AS holdtime FROM YourTableName -- 替换为实际表名 GROUP BY ID, StartDate, -- 按30分钟区间分组 DATEDIFF(MINUTE, 0, StartTime) / 30 ORDER BY ID, StartDate, intervalStartTime;
方案说明
- 区间计算逻辑:
- 用
DATEDIFF(MINUTE, 0, StartTime)计算从SQL Server基准时间(1900-01-01 00:00:00)到当前StartTime的总分钟数。 - 除以30取整后再乘以30,得到该时间所属30分钟区间的起始分钟数,再通过
DATEADD转换为时间格式。 - 区间结束时间为起始时间加30分钟。
- 用
- 分组求和:按
ID、StartDate和计算出的区间分组,对holdtime求和得到每个区间的总等待时长。 - 优势:基于集合操作,执行效率远高于循环,逻辑简洁易维护,直接匹配需求输出格式。
内容的提问来源于stack exchange,提问作者Alejandro Ruiz
相关产品推荐
相关产品推荐

