сделать число посетителей за день равным 0, которого нет в базе данных MySQL

У меня есть таблица

___________________________________________ id | user | Visitor | timestamp ___________________________________________ 13 |username |abc | 2014-01-15 15:01:44 14 |username |abc | 2014-01-15 15:01:44 15 |username |abc | 2014-01-18 15:01:44 16 |username |abc | 2014-01-18 15:01:44 ___________________________________________ 

Я использовал QUERY для COUNT нет посетителя USER abc в течение последних 7 дней с СЕГОДНЯ.

 SELECT DATE(`timestamp`) as `date`, COUNT(*) as `count` FROM `table` WHERE (`timestamp` >= (NOW() - INTERVAL 7 DAY)) AND (`user` = 'username') GROUP BY `date`; 

Он получает следующий результат:

 ______________________________ date | count ______________________________ 2014-01-15 | 2 2014-01-18 | 2 

Но мне нужно:

 ______________________________ date | count ______________________________ 2014-01-15 | 2 2014-01-16 | 0 // Make 0 for the day which is not present 2014-01-17 | 0 // Make 0 for the day which is not present 2014-01-18 | 2 

Что будет для этого вопросом?

Используйте subquer для создания таблицы со всеми днями на прошлой неделе, затем присоедините это к своей таблице:

 SELECT `date`, IFNULL(COUNT(*), 0) as `count` FROM (SELECT DATE(NOW()) AS `date` UNION SELECT DATE(DATE_SUB(NOW(), INTERVAL 1 DAY)) UNION SELECT DATE(DATE_SUB(NOW(), INTERVAL 2 DAY)) UNION SELECT DATE(DATE_SUB(NOW(), INTERVAL 3 DAY)) UNION SELECT DATE(DATE_SUB(NOW(), INTERVAL 4 DAY)) UNION SELECT DATE(DATE_SUB(NOW(), INTERVAL 5 DAY)) UNION SELECT DATE(DATE_SUB(NOW(), INTERVAL 6 DAY)) UNION SELECT DATE(DATE_SUB(NOW(), INTERVAL 7 DAY))) AS days LEFT JOIN `table` ON DATE(`timestamp`) = `date` WHERE (`timestamp` >= (NOW() - INTERVAL 7 DAY)) AND (`user` = 'username') GROUP BY `date`; 

Это хорошо известная проблема о разрыве – и у нее много ответов на SO.

Во-первых, самый очевидный способ – использовать таблицу, которая будет удерживать все даты подряд (для текущего года в качестве образца). Например, пусть это будет таблица dates с полем record_date (она содержит дату), тогда ваш запрос будет выглядеть так:

 SELECT DATE(`timestamp`) as `date`, COUNT(`dates`.`id`) as `count` FROM `dates` LEFT JOIN `table` ON `dates`.`record_date` = DATE(`table`.`timestamp`) WHERE (`timestamp` >= (NOW() - INTERVAL 7 DAY)) AND (`user` = 'username') GROUP BY `dates`.`record_date` 

Так вы будете возвращать нули через LEFT JOIN .

Существует еще один, более сложный способ добиться этого с помощью запроса генератора последовательности. На самом деле в MySQL нет последовательностей, но вы можете генерировать последовательные значения из CROSS JOIN а затем применять их к выбору даты. Например:

 SELECT DATE_ADD(CURDATE() - INTERVAL 1 WEEK, INTERVAL sequence.id DAY) FROM (SELECT (two_1.id + two_2.id + two_4.id + two_8.id + two_16.id) AS id FROM (SELECT 0 AS id UNION ALL SELECT 1 AS id) AS two_1 CROSS JOIN (SELECT 0 AS id UNION ALL SELECT 2 AS id) AS two_2 CROSS JOIN (SELECT 0 AS id UNION ALL SELECT 4 AS id) AS two_4 CROSS JOIN (SELECT 0 AS id UNION ALL SELECT 8 AS id) AS two_8 CROSS JOIN (SELECT 0 AS id UNION ALL SELECT 16 AS id) AS two_16 ) AS sequence WHERE sequence.id<7 

– будут отображаться даты на предыдущей неделе, поэтому вы сможете использовать это вместо создания и заполнения временной таблицы, как в первую очередь. Хорошая вещь в этом вопросе – это статичность, поэтому вам не придется добавлять другую часть UNION если вы хотите увеличить интервал выбора.