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

SQL按类别与日期分组统计时补全缺失日期并置计数为0的方法

解决方案

你遇到的是分组统计时缺失无数据维度的问题,核心解决思路是先生成「所有分类+所有待统计日期」的全量组合,再左关联你原有统计结果,将空值填充为0即可,完整实现如下:

实现步骤

1. 生成连续日期序列

首先生成你需要覆盖的时间范围内的所有连续日期,主流数据库都可以用递归CTE实现:

-- 递归生成2021-08-01到2021-08-31的所有日期,可替换为你需要的时间范围
WITH RECURSIVE date_range AS (
    SELECT '2021-08-01' AS date
    UNION ALL
    SELECT DATE_ADD(date, INTERVAL 1 DAY) 
    FROM date_range 
    WHERE date < '2021-08-31'
)

2. 生成全部分类列表

取出log表中所有去重的分类:

all_categories AS (
    SELECT DISTINCT category FROM log
)

3. 生成全量分类+日期组合

通过笛卡尔积得到每个分类对应全部待统计日期的完整组合:

full_combinations AS (
    SELECT c.category, d.date 
    FROM all_categories c
    CROSS JOIN date_range d
)

4. 关联统计结果补全空值

将全量组合左关联你原有的每日统计结果,没有数据的日期total自动填充为0:

daily_stats AS (
    SELECT 
        category, 
        COUNT(category) as total, 
        CAST(date AS DATE) as stat_date
    FROM log
    GROUP BY category, CAST(date AS DATE)
)
-- 最终查询
SELECT 
    fc.category,
    fc.date,
    COALESCE(ds.total, 0) AS total
FROM full_combinations fc
LEFT JOIN daily_stats ds 
    ON fc.category = ds.category 
    AND fc.date = ds.stat_date
ORDER BY fc.category ASC, fc.date ASC
LIMIT 100;

完整查询语句(可直接修改参数使用)

WITH RECURSIVE date_range AS (
    SELECT '2021-08-01' AS date -- 替换为你的统计起始日期
    UNION ALL
    SELECT DATE_ADD(date, INTERVAL 1 DAY) 
    FROM date_range 
    WHERE date < '2021-08-31' -- 替换为你的统计结束日期
),
all_categories AS (
    SELECT DISTINCT category FROM log
),
full_combinations AS (
    SELECT c.category, d.date 
    FROM all_categories c
    CROSS JOIN date_range d
),
daily_stats AS (
    SELECT 
        category, 
        COUNT(category) as total, 
        CAST(date AS DATE) as stat_date
    FROM log
    GROUP BY category, CAST(date AS DATE)
)
SELECT 
    fc.category,
    fc.date,
    COALESCE(ds.total, 0) AS total
FROM full_combinations fc
LEFT JOIN daily_stats ds 
    ON fc.category = ds.category 
    AND fc.date = ds.stat_date
ORDER BY fc.category ASC, fc.date ASC
LIMIT 100;

注意事项

  • 上述语法为MySQL写法,其他数据库仅需调整日期运算语法即可:PostgreSQL写为date + INTERVAL '1 day',SQL Server写为DATEADD(day, 1, date)
  • 如果数据量较大,建议预先维护一张专门的日期维度表,直接查询维度表获取连续日期,性能远高于递归CTE
  • 可按需给log表的date、category字段添加索引,提升统计查询效率

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:42:02