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

MySQL如何按10分钟间隔统计聚合结果 包含无数据时段0值

按10分钟间隔统计含无数据时段的SQL调整方案

核心解决思路是先构造从统计起始时间到当前时间的完整10分钟刻度序列,再和你现有统计结果左关联,无匹配的时段自动补0即可。

完整实现SQL(支持MySQL 8.0+、Hive、Spark SQL等支持递归CTE的引擎)

WITH RECURSIVE time_series AS (
    -- 自定义统计起始时间,这里按你的示例取2021-09-16 09:10:00,可根据需求调整
    SELECT '2021-09-16 09:10:00' AS time_slot
    UNION ALL
    -- 每次递增加10分钟,直到时间超过当前时间
    SELECT DATE_ADD(time_slot, INTERVAL 10 MINUTE)
    FROM time_series
    WHERE time_slot < NOW()
),
access_stats AS (
    -- 你原有的统计逻辑,可直接复用
    SELECT
        CASE 
            WHEN SUBSTR(in_datetime,15,2) < '10' THEN CONCAT(SUBSTR(in_datetime,12,2),':00')
            WHEN SUBSTR(in_datetime,15,2) >='10' AND SUBSTR(in_datetime,15,2)<'20' THEN CONCAT(SUBSTR(in_datetime,12,2),':10')
            WHEN SUBSTR(in_datetime,15,2) >='20' AND SUBSTR(in_datetime,15,2)<'30' THEN CONCAT(SUBSTR(in_datetime,12,2),':20')
            WHEN SUBSTR(in_datetime,15,2) >='30' AND SUBSTR(in_datetime,15,2)<'40' THEN CONCAT(SUBSTR(in_datetime,12,2),':30')
            WHEN SUBSTR(in_datetime,15,2) >='40' AND SUBSTR(in_datetime,15,2)<'50' THEN CONCAT(SUBSTR(in_datetime,12,2),':40')
            WHEN SUBSTR(in_datetime,15,2) >='50' AND SUBSTR(in_datetime,15,2)<'60' THEN CONCAT(SUBSTR(in_datetime,12,2),':50')
        END as hhmm,
        COUNT(access_no) as au
    FROM tbl_access
    WHERE DATE(out_datetime) = STR_TO_DATE('20210916', '%Y%m%d')
    AND in_datetime IS NOT NULL
    GROUP BY 
        SUBSTR(in_datetime,1,10),
        CASE 
            WHEN SUBSTR(in_datetime,15,2) < '10' THEN CONCAT(SUBSTR(in_datetime,12,2),':00')
            WHEN SUBSTR(in_datetime,15,2) >='10' AND SUBSTR(in_datetime,15,2)<'20' THEN CONCAT(SUBSTR(in_datetime,12,2),':10')
            WHEN SUBSTR(in_datetime,15,2) >='20' AND SUBSTR(in_datetime,15,2)<'30' THEN CONCAT(SUBSTR(in_datetime,12,2),':20')
            WHEN SUBSTR(in_datetime,15,2) >='30' AND SUBSTR(in_datetime,15,2)<'40' THEN CONCAT(SUBSTR(in_datetime,12,2),':30')
            WHEN SUBSTR(in_datetime,15,2) >='40' AND SUBSTR(in_datetime,15,2)<'50' THEN CONCAT(SUBSTR(in_datetime,12,2),':40')
            WHEN SUBSTR(in_datetime,15,2) >='50' AND SUBSTR(in_datetime,15,2)<'60' THEN CONCAT(SUBSTR(in_datetime,12,2),':50')
        END
)
-- 最终关联查询补全空时段
SELECT 
    ts.`hh:mm`,
    IFNULL(stats.au, 0) AS au
FROM (
    -- 把时间序列格式化为hh:mm格式
    SELECT DATE_FORMAT(time_slot, '%H:%i') AS `hh:mm`
    FROM time_series
) ts
LEFT JOIN access_stats stats ON ts.`hh:mm` = stats.hhmm
ORDER BY ts.`hh:mm`

优化提示

你原有的多层case判断截取10分钟刻度的逻辑可以简化,仅用一行代码即可实现相同效果:
DATE_FORMAT(DATE_ADD(in_datetime, INTERVAL -(MINUTE(in_datetime) % 10) MINUTE), '%H:%i')

低版本MySQL兼容方案

如果使用不支持递归CTE的低版本MySQL,可提前创建一张时间维度辅助表,提前录入所有可能用到的hh:mm 10分钟刻度,直接查询该维度表左关联你的统计结果即可,逻辑和上述方案一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 21:06:00