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
精彩评论