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

MySQL如何统计近7个月(含当月)每月观测数,无数据月份补0?

实现方案

核心思路是先生成最近7个自然月的连续月份序列,再将序列与观测表左关联统计,即可保留所有月份,无数据的月份统计值自动为0。

MySQL 8.0及以上版本解法(推荐)

使用递归CTE生成连续月份序列,代码如下:

WITH RECURSIVE months AS (
    -- 生成当月起始时间作为基准值
    SELECT DATE_FORMAT(CURDATE(), '%Y-%m-01') AS month_start, 
           YEAR(CURDATE()) AS year_num, 
           MONTH(CURDATE()) AS month_num
    UNION ALL
    -- 递归向前推导6个月,共生成7条月份记录
    SELECT DATE_SUB(month_start, INTERVAL 1 MONTH),
           YEAR(DATE_SUB(month_start, INTERVAL 1 MONTH)),
           MONTH(DATE_SUB(month_start, INTERVAL 1 MONTH))
    FROM months
    WHERE month_start > DATE_SUB(DATE_FORMAT(CURDATE(), '%Y-%m-01'), INTERVAL 6 MONTH)
)
SELECT 
    m.year_num,
    m.month_num,
    COUNT(o.observation) AS observ
FROM months m
LEFT JOIN observations o 
    ON DATE_FORMAT(o.created_at, '%Y-%m-01') = m.month_start
    AND o.created_at >= DATE_ADD(NOW(), INTERVAL -6 MONTH)
GROUP BY m.year_num, m.month_num
ORDER BY m.year_num ASC, m.month_num ASC;

MySQL 5.x版本解法(不支持递归CTE场景)

通过手动构造数字序列生成月份范围,代码如下:

SELECT 
    YEAR(DATE_SUB(DATE_FORMAT(CURDATE(), '%Y-%m-01'), INTERVAL nums.n MONTH)) AS year_num,
    MONTH(DATE_SUB(DATE_FORMAT(CURDATE(), '%Y-%m-01'), INTERVAL nums.n MONTH)) AS month_num,
    COUNT(o.observation) AS observ
FROM (
    SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL 
    SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
) nums
LEFT JOIN observations o 
    ON o.created_at >= DATE_SUB(DATE_FORMAT(CURDATE(), '%Y-%m-01'), INTERVAL nums.n MONTH)
    AND o.created_at < DATE_SUB(DATE_FORMAT(CURDATE(), '%Y-%m-01'), INTERVAL nums.n - 1 MONTH)
GROUP BY nums.n, year_num, month_num
ORDER BY year_num ASC, month_num ASC;

注意事项

  • 你原有查询存在一个隐藏问题:仅按月份分组未关联年份,跨年度统计时会将不同年份的同一月份数据合并,导致统计错误,上述解法已新增年份维度避免该问题。
  • 若不需要展示年份,可在最终查询字段中去掉year_num即可,不影响统计逻辑正确性。

内容的提问来源于stack exchange,提问作者Arley Steven Lache Rueda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 06:15:02