Можно ли это сделать с помощью чисто SQL-запроса или мне нужно использовать некоторую php-логику?
Да, лучше создать таблицу чисел (один столбец N), которая не содержит ничего, кроме чисел от 0 до 999. Она может использоваться для многих вещей, не в последнюю очередь для запроса, подобного приведенному ниже:
SELECT COUNT(t.click_date) as clicks,
DATE_FORMAT(adddate($start_date, interval N day), '%d %M %Y') as point
FROM Numbers
LEFT JOIN tracking t
ON t.click_date >= adddate($start_date, interval N day)
and t.click_date < adddate($start_date, interval (N+1) day)
WHERE N between 0 and datediff($start_date, $end_date)
GROUP BY N
Кстати, почему у меня 0 февраля 2011 года в качестве моего первого свидания
Вы используете неправильный формат. ВЕРХНИЙ случай W не ниже для дня недели, поэтому '% W% M% Y' или '% d% M% Y' для дня месяца.
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-format
может быть, моя GROUP BY не работает правильно?
Вы используете GROUP BY DAY(FROM_UNIXTIME(click_date))
note "день" не день недели, но вы отображаете (или пытаетесь) "% W" (день недели) - выберите один, не делайте смешивать их.
РЕДАКТИРОВАТЬ: Если вы предпочитаете не материализовать (создать в качестве реальной таблицы) таблицу последовательности чисел, вы можете создать ее на лету. Это не будет красиво.
Примечание: N1, N2 и N3 ниже объединяются, чтобы дать возможный диапазон 0-999
SELECT COUNT(t.click_date) as clicks,
DATE_FORMAT(adddate($start_date, interval N day), '%d %M %Y') as point
FROM (
select N1 * 100 + N2 * 10 + N3 as N
from (
select 0 N1 union all select 1 union all select 2 union all
select 3 union all select 4 union all select 5 union all
select 6 union all select 7 union all
select 8 union all select 9) N1
cross join (
select 0 N2 union all select 1 union all select 2 union all
select 3 union all select 4 union all select 5 union all
select 6 union all select 7 union all
select 8 union all select 9) N2
cross join (
select 0 N3 union all select 1 union all select 2 union all
select 3 union all select 4 union all select 5 union all
select 6 union all select 7 union all
select 8 union all select 9) N3
) Numbers
LEFT JOIN tracking t
ON t.click_date >= adddate($start_date, interval N day)
and t.click_date < adddate($start_date, interval (N+1) day)
WHERE N between 0 and datediff($start_date, $end_date)
GROUP BY N
РЕДАКТИРОВАНИЕ № 2: Таблица прямых дат
Поместите это в новое окно в phpMyAdmin или запустите как пакет. Он создает таблицу с именем Dates, с каждой отдельной датой от дня 1900-01-01
(или изменения в сценарии) до 2300-01-01
(или изменения).
DROP PROCEDURE IF EXISTS FillDateTable;
delimiter //
CREATE PROCEDURE FillDateTable()
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
drop table if exists datetable;
create table datetable (thedate datetime primary key, isweekday smallint);
SET @x := date('1900-01-01');
REPEAT
insert into datetable (thedate, isweekday) SELECT @x, case when dayofweek(@x) in (1,7) then 0 else 1 end;
SET @x := date_add(@x, interval 1 day);
UNTIL @x > date('2300-01-01') END REPEAT;
END//
delimiter ;
CALL FillDateTable;
С такой таблицей утилит ваш запрос может быть просто
SELECT COUNT(t.click_date) as clicks,
DATE_FORMAT(thedate, '%d %M %Y') as point
FROM Dates
LEFT JOIN tracking t
ON t.click_date >= thedate
and t.click_date < adddate(thedate, interval 1 day)
WHERE thedate between $start_date and $end_date
GROUP BY thedate