开发者

MySQL Counts per day when count is 0

I have a MySQL query:

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;

Which correctly returns something like:

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

However, I would like to also get the dates where there was 0 counts. So assuming startDate is 2011-08-10 and endDate is 2011-08-15, I would see:

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

I am using PHP so in theory I coul开发者_如何学运维d do some complex looping and fill up the gaps somehow, but I am wondering if there is a better solution?

Note that if no good MySQL solution exist, I'm also open to good PHP solutions


If you want count items per day with 0 result,

try this :

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)

output :

[
    {
        "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"
    }
]


I think a possible solution you can look for is to create a table populated with all the dates and then have a join with the table.The table wont be very big as it contains just 365 rows for one year.Prepopulate this table and join with this table for your query.

The benefit here is you dont have do any complex looping of dates inside your php every time this query get called. you populated your table once and use it over and over.


You need to make a table with dates and join against that.

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

Now do the following query

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜