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

MySQL跨天时间区间数据分组统计查询问题

跨排班周期统计SQL修正方案

原代码核心错误

  • 时段过滤逻辑完全失效:HOUR(sd.timestamp) >= 20 AND HOUR(sd.timestamp) < 4 是恒不成立的判断,时间字段的小时值范围是0-23,不可能同时满足大于等于20、小于4,直接过滤掉了跨夜班次0-4点的所有数据
  • 班次归属逻辑硬编码:DATE(sd.timestamp - INTERVAL(LEAST(20, 4)) HOUR) 偏移量固定为4小时,无法适配非跨夜、全天统计的场景
  • 递归序列长度写死:硬编码value < 29只能生成30个周期,无法适配周、自定义长度的统计需求
  • 周期表排序逻辑错误:period CTE中ORDER BY value DESC会导致周期顺序倒排,关联时容易出现匹配错位

通用修正代码(支持全部三类场景)

核心思路是把排班规则、统计区间全部参数化,通过生成完整的班次周期表做范围关联,避免硬编码小时判断,同时解决跨夜数据归属问题。

-- 以下参数根据实际统计需求修改即可
SET @stat_start = '2022-06-01 00:00:00'; -- 统计范围起始时间
SET @stat_end = '2022-07-01 00:00:00';   -- 统计范围结束时间
SET @shift_start = 20;                   -- 每日班次开始小时(20即20:00)
SET @shift_end = 4;                      -- 每日班次结束小时(4即次日04:00,非跨夜班次填当日时间即可)
SET @cross_night = @shift_end < @shift_start; -- 自动识别是否为跨夜班次

WITH RECURSIVE seq AS (
    SELECT 0 AS num
    UNION ALL
    SELECT num + 1
    FROM seq
    -- 自动计算需要生成的周期数,跨夜场景多补1天覆盖最后一个班次的凌晨时段
    WHERE num < TIMESTAMPDIFF(DAY, @stat_start, @stat_end) + IF(@cross_night, 1, 0)
),
shift_period AS (
    SELECT
        DATE(@stat_start + INTERVAL num DAY) AS stat_date,
        @stat_start + INTERVAL num DAY + INTERVAL @shift_start HOUR AS period_start,
        @stat_start + INTERVAL num DAY + INTERVAL @shift_end HOUR + INTERVAL IF(@cross_night, 1, 0) DAY AS period_end
    FROM seq
    -- 过滤超出统计范围的无效班次
    HAVING period_start < @stat_end + INTERVAL IF(@cross_night, 1, 0) DAY
)
SELECT
    sp.stat_date,
    SUM(IFNULL(sd.need_calc_field, 0)) AS total_count -- 替换为实际需要聚合的字段
FROM shift_period sp
LEFT JOIN sensor_data sd
    ON sd.timestamp >= sp.period_start
    AND sd.timestamp < sp.period_end
-- 不需要展示无数据的边缘日期可以打开下面的过滤条件
-- WHERE sp.stat_date >= DATE(@stat_start) AND sp.stat_date < DATE(@stat_end)
GROUP BY sp.stat_date
ORDER BY sp.stat_date;

三类典型场景参数配置

  • 跨夜班次统计(2022年6月1日-7月1日,每日20:00至次日04:00):
    @stat_start='2022-06-01'、@stat_end='2022-07-01'、@shift_start=20、@shift_end=4
  • 非跨夜班次统计(2022年6月1日-6月30日,每日04:00至20:00):
    @stat_start='2022-06-01'、@stat_end='2022-07-01'、@shift_start=4、@shift_end=20
  • 全天统计(2022年6月1日-6月30日,每日00:00至23:59):
    @stat_start='2022-06-01'、@stat_end='2022-07-01'、@shift_start=0、@shift_end=24

调整说明

  • 废弃原有的HOUR()函数过滤逻辑,改用班次周期范围匹配,不会漏算跨夜时段数据,同时可以命中timestamp字段的索引,查询性能更高
  • 所有规则参数抽离,不需要修改核心查询逻辑,仅调整参数即可适配周、月、任意自定义时间区间,以及跨夜/不跨夜/全天的排班规则
  • 递归序列长度自动计算,不需要硬编码天数,跨夜场景自动补全最后一个班次的凌晨时段
  • 采用左关联方式聚合,无数据的日期也会返回0值,不会出现日期缺漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 17:45:38