【问题标题】:group by date, even if there is no entry for the date按日期分组,即使没有日期条目
【发布时间】:2016-01-21 19:21:19
【问题描述】:

我想通过计算同一天创建的条目数来可视化我的条目。

SELECT dayname(created_at), count(*) FROM logs
group by day(created_at)
ORDER BY created_at desc
LIMIT 7

所以我得到类似的东西:

Thursday    4  
Wednesday   12  
Monday  4  
Sunday  1  
Saturday    20  
Friday  23  
Thursday    10

但我也想把星期二放在那里,所以我有一个星期。

有没有办法用完整的 mysql 来做到这一点,还是我需要先更新结果才能将它提供给图表?

编辑:

这是最后的查询:

SELECT
    DAYNAME(date_add(NOW(), interval days.id day)) AS day,
    count(logs.id) AS amount
FROM days LEFT OUTER JOIN
    (SELECT *
    FROM logs
    WHERE TIMESTAMPDIFF(DAY,DATE(created_at),now()) < 7) logs
    on datediff(created_at, NOW()) = days.id
GROUP BY days.id
ORDER BY days.id desc;

表格 days 包括从 0 到 -6 的数字

【问题讨论】:

    标签: mysql sql date group-by


    【解决方案1】:

    您只需要一个偏移量表,它可以是一个真实的表或像select 0 ofs union all select -1 ... 这样动态构建的东西。

    create table days (ofs int);
    insert into days (ofs) values
         (0), (-1), (-2), (-3),
        (-4), (-5), (-6), (-7);
    
    select
        date_add('20160121', interval days.ofs day) as created_at,
        count(data.id) as cnt
    from days left outer join logs data
        on datediff(data.created_at, '20160121') = days.ofs
    group by days.ofs
    order by days.ofs;
    

    http://sqlfiddle.com/#!9/3e6bc7/1

    为了提高性能,最好限制在数据(日志)表中的搜索:

    select
        date_add('20160121', interval days.ofs day) as created_at,
        count(data.id) as cnt
    from days left outer join
        (select * from logs where created_at between <start> and <end>) data
        on datediff(data.created_at, '20160121') = days.offset
    group by days.offset
    order by days.offset;
    

    一个缺点是您必须在几个表达式中使用固定的锚日期对其进行参数化。将真实日期表放在某处可能会更好,这样您就不必进行计算了。

    【讨论】:

    • @mimo 酷。如果您实际上不想在报告中涵盖 8 天,希望您去掉 -7。
    【解决方案2】:

    对日期表使用RIGHT JOIN,这样您就可以请求每一天和所有天的数据,无论某些天是否有数据,简单地说,mull 天将显示为 CERO 或 NULL。

    您可以创建日期表,某种日历表。

     id_day | day_date   |
     --------------------
     1      | 2016-01-01 |
     2      | 2016-01-02 |
     .
     .
     365    | 2016-12-31 |
    

    使用此表,您可以关联日期,然后使用 MYSQL DATE AND TIME FUNCTIONS 提取日、月、周等任何您想要的内容

     SELECT t2.dayname(day_date), count(t1.created_at) FROM logs t1 right join dates_table t2 on t1.created_at=t2.day_date group by t2.day_date ORDER BY t1.created_at desc LIMIT 7
    

    【讨论】:

    • 我只找到了带有硬编码日期的左连接示例。
    • 但这不只是一个小问题吗?我必须每年更新这个表,所以我不能即时创建一个返回过去 7 天的表吗?
    • 您可以每年创建一次包含 365 行的年度表,这可以通过循环轻松完成,或者每周创建一个 7 天的表。重要的是,如果在您的日志表中没有为给定日期插入任何事件,那么如果没有外部表的帮助,就无法使缺失的日期出现。我的意见是年表非常有帮助。我从 Kimaballs 的模特书籍中学到了。
    • 是的,我认为包含所有日期的表格是最佳选择。我只在工作日尝试过,但您无法订购。
    猜你喜欢
    • 2015-09-08
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 2011-02-19
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多