这可以通过纯 SQL 查询来完成,还是我必须使用一些 php 逻辑?
是的,最好创建一个只包含数字 0 到 999 的数字表(单列 N)。它可以用于很多事情,尤其是像下面这样的查询:
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
顺便说一句,为什么我的第一次约会是 2011 年 2 月 0 日
您使用了错误的格式。对于星期几,大写的 W 不会小,所以 '%W %M %Y' 或 '%d %M %Y' 代表 day-of-月。
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)) 注意 "day" 不是工作日,但您正在显示(或尝试)"%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