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

BigQuery按1小时间隔拆分班次时长查询异常排查

问题根因

现有SQL没有对每个小时切片的时长做重新计算,直接读取了原始表中存储的整班次总时长duration_in_hours,因此所有匹配到的整点区间都会显示整班次的3小时。
之前在其他数据表能得到正确结果,是因为那些表的duration_in_hours本身就是按小时粒度预拆分存储的,不需要二次计算;当前表存储的是班次维度的总时长,直接读取必然返回错误值。
另外原SQL存在两处语法瑕疵:

  • 字段名误写为带空格的duration in hours,和表中实际的下划线命名字段duration_in_hours不匹配
  • SELECT子句末尾shift_end_at后多了一个冗余逗号,部分SQL引擎会直接报语法错误
计算逻辑

每个整点区间的实际落入时长按三类场景分别计算即可:

  • 班次起始所在小时:用「当前整点+1小时的区间结束时间」减去「班次开始时间」,结果换算为小时单位
  • 班次结束所在小时:用「班次结束时间」减去「当前整点的区间开始时间」,结果换算为小时单位
  • 完全被班次覆盖的中间小时:固定返回1小时
修正后SQL(兼容BigQuery语法,和你现有生成小时维度的逻辑一致)
SELECT
  date,
  TIME(hour, 0, 0) AS time,
  CASE
    -- 计算班次起始小时的实际时长
    WHEN TIME(hour, 0, 0) = TIME_TRUNC(shift_start_at, HOUR)
      THEN TIMESTAMP_DIFF(
        TIMESTAMP_ADD(TIMESTAMP(date, TIME(hour, 0, 0)), INTERVAL 1 HOUR),
        TIMESTAMP(date, shift_start_at),
        SECOND
      ) / 3600
    -- 计算班次结束小时的实际时长
    WHEN TIME(hour, 0, 0) = TIME_TRUNC(shift_end_at, HOUR)
      THEN TIMESTAMP_DIFF(
        TIMESTAMP(date, shift_end_at),
        TIMESTAMP(date, TIME(hour, 0, 0)),
        SECOND
      ) / 3600
    -- 中间完整覆盖的小时固定为1小时
    ELSE 1
  END AS duration_in_hours,
  shift_start_at,
  shift_end_at
FROM a, UNNEST(GENERATE_ARRAY(0, 23)) AS hour
WHERE
  TIME(hour, 0, 0) >= TIME_TRUNC(shift_start_at, HOUR)
  AND TIME(hour, 0, 0) < shift_end_at
效果验证

针对你给出的2022-05-24班次(19:30:00-22:30:00),运行上述SQL会返回如下结果,完全符合预期:

  • 19:00:00区间:0.5小时
  • 20:00:00区间:1小时
  • 21:00:00区间:1小时
  • 22:00:00区间:0.5小时

注:如果存在跨天班次,需要调整时间拼接逻辑,从你给出的样例来看所有班次均为单日区间,当前逻辑可直接使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 16:54:21