You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用MS SQL计算两个时间点在半小时区间的时长分布?

MS SQL按半小时区间统计时长的实现方案

核心思路

不需要用循环处理,SQL是基于集合的语言,通过预生成所有半小时区间,再将目标时间范围与每个区间计算交集时长,是最高效的处理方式。

单条时间范围的统计示例

假设已知起始时间@start_time = '08:47',结束时间@end_time = '09:07',可以用以下代码直接输出各区间的时长:

DECLARE @start_time time = '08:47', @end_time time = '09:07';

WITH HalfHourIntervals AS (
    -- 生成一天内所有48个半小时区间
    SELECT 
        DATEADD(minute, 30 * n, CAST('00:00' AS time)) AS IntervalStart,
        DATEADD(minute, 30 * (n + 1), CAST('00:00' AS time)) AS IntervalEnd
    FROM (
        -- 生成0到47的数字序列,对应48个区间
        SELECT TOP 48 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 AS n
        FROM sys.all_columns -- 利用系统表生成数字,也可以用自定义数字表
    ) t
)
SELECT 
    CONVERT(varchar(5), IntervalStart) + ' - ' + CONVERT(varchar(5), IntervalEnd) AS TimeInterval,
    -- 计算当前区间与目标时间范围的交集时长
    DATEDIFF(minute, 
        MAX(@start_time, IntervalStart), 
        MIN(@end_time, IntervalEnd)
    ) AS DurationMinutes
FROM HalfHourIntervals
-- 过滤出与目标时间范围有重叠的区间
WHERE IntervalStart < @end_time
  AND IntervalEnd > @start_time
ORDER BY IntervalStart;

执行后会得到预期结果:

TimeInterval | DurationMinutes
-------------|-----------------
08:30 - 09:00| 13
09:00 - 09:30| 7

批量时间记录的统计方案

如果是处理表中的批量时间记录(比如表TimeRecords包含id、start_time、end_time字段),只需将CTE生成的区间与表做交叉连接,再计算每条记录的区间时长:

WITH HalfHourIntervals AS (
    SELECT 
        DATEADD(minute, 30 * n, CAST('00:00' AS time)) AS IntervalStart,
        DATEADD(minute, 30 * (n + 1), CAST('00:00' AS time)) AS IntervalEnd
    FROM (
        SELECT TOP 48 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 AS n
        FROM sys.all_columns
    ) t
)
SELECT 
    tr.id,
    CONVERT(varchar(5), hhi.IntervalStart) + ' - ' + CONVERT(varchar(5), hhi.IntervalEnd) AS TimeInterval,
    DATEDIFF(minute, 
        MAX(tr.start_time, hhi.IntervalStart), 
        MIN(tr.end_time, hhi.IntervalEnd)
    ) AS DurationMinutes
FROM TimeRecords tr
CROSS JOIN HalfHourIntervals hhi
WHERE hhi.IntervalStart < tr.end_time
  AND hhi.IntervalEnd > tr.start_time
ORDER BY tr.id, hhi.IntervalStart;

为什么不推荐用循环

循环属于逐行处理的方式,在MS SQL中面对大量数据时性能极差,远不如基于集合的操作高效。预生成区间的方式只需一次生成所有可能的区间,再通过集合运算完成统计,无论是执行速度还是维护性都更优。

内容的提问来源于stack exchange,提问作者RustyStupidSQL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 22:50:18