【问题标题】:MySQL Counts per day when count is 0当计数为 0 时,MySQL 每天计数
【发布时间】:2011-08-30 08:55:13
【问题描述】:

我有一个 MySQL 查询:

SELECT COUNT(*) AS total,  DATE_FORMAT(event.serverTime,'%Y-%m-%d') AS sdate
                    FROM event
                    WHERE
                    event.serverTime >= :startDate
                    AND event.serverTime <= :endDate 
                    GROUP BY sdate;

正确返回如下内容:

2011-08-10 => 5  
2011-08-15 => 6

但是,我还想获取计数为 0 的日期。所以假设 startDate 是 2011-08-10 而 endDate 是 2011-08-15,我会看到:

2011-08-10 => 5  
2011-08-11 => 0  
2011-08-12 => 0  
2011-08-13 => 0  
2011-08-14 => 0  
2011-08-15 => 6

我正在使用 PHP,所以理论上我可以做一些复杂的循环并以某种方式填补空白,但我想知道是否有更好的解决方案?

请注意,如果不存在好的 MySQL 解决方案,我也愿意接受好的 PHP 解决方案

【问题讨论】:

  • 当计数为零时是否填充事件表
  • 不,这就是问题所在。如果 2011-08-11 没有事件,那么当天就没有数据,因此没有什么可计算的。我什至不确定是否有解决该问题的方法...
  • 请注意,如果没有好的 MySQL 解决方案存在,我也愿意接受好的 PHP 解决方案

标签: php mysql sql timestamp


【解决方案1】:

如果你想每天计算 0 个结果的项目,

试试这个:

set @date_start := (SELECT MIN(date_col) FROM my_table), 
    @date_end := (SELECT MAX(date_col) FROM my_table), 
    @i := 0;
SELECT DATE(ADDDATE(@date_start, INTERVAL @i:=@i+1 DAY)) AS date,
IFNULL((
    SELECT COUNT(*) FROM my_table AS m2
    WHERE DATE(m2.date_col) = DATE(ADDDATE(@date_start, INTERVAL @i DAY))
),0) AS total
FROM my_table AS m1
HAVING @i < DATEDIFF(@date_end, @date_start)

输出:

[
    {
        "date": "2017-03-01",
        "total": "0"
    },
    {
        "date": "2017-03-02",
        "total": "0"
    },
    {
        "date": "2017-03-03",
        "total": "0"
    },
    {
        "date": "2017-03-04",
        "total": "0"
    },
    {
        "date": "2017-03-05",
        "total": "0"
    }
]

【讨论】:

  • 恕我直言,这应该是正确的答案。我已经修改了一些内容以使其正常工作。
【解决方案2】:

我认为您可以寻找的一个可能的解决方案是创建一个填充了所有日期的表,然后与该表连接。该表不会很大,因为它仅包含 365 行一年。预填充此表并加入此表以供您查询。

这里的好处是每次调用此查询时,您都不必在 php 中执行任何复杂的日期循环。你填充了你的表一次,然后一遍又一遍地使用它。

【讨论】:

    【解决方案3】:

    您需要制作一个带有日期的表格并加入。

    table temp_dates
    id integer auto_increment PK
    mydate date  <<-- consecutive dates
    

    现在进行以下查询

    SELECT count(e.servertime) as total
           , td.mydate as sdate
    FROM event e
    RIGHT JOIN temp_dates td ON (td.mydate = date(e.servertime))
    WHERE td.mydate BETWEEN :startdate AND :enddate
    GROUP BY td.mydate 
    HAVING total = 0
    

    【讨论】:

    • 所以我必须创建一个包含世界上所有可能日期的表格?
    • 不,只有你感兴趣的日期,在BETWEEN :startdate AND :enddate范围内的日期
    • 哦,实际上,这个确切的查询可能有效,但如果我有其他“AND”语句,例如“AND event.type=5”,那么问题就来了,因为它消除了空行。也许“拥有”会有所帮助?
    • @nute,哦,你想要0行的日期,没问题,更新了答案。
    • 不不,你的查询是正确的,我想要那些有 0 和非 0 的。你可以还原。我的问题是在“事件”表上添加新参数时。我通过将条件语句放入 ON() 而不是 WHERE 来解决它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 2020-07-22
    • 1970-01-01
    • 2016-12-30
    相关资源
    最近更新 更多