你需要一个
OUTER JOIN
从开始到结束的每一天,因为如果你使用
INNER JOIN
它会将输出限制为仅连接的日期(即报告表中的那些日期)。
此外,当您使用
外部连接
你必须注意
where clause
不要引起
implicit inner join
; 例如
AND域_id=1
如果在where子句中使用将禁止任何不满足该条件的行,但当用作联接条件时,它仅限制报表表的行。
SELECT
COUNT(r.domain_id)
, all_dates.Date AS the_date
, domain_id
FROM (
SELECT DATE_ADD(curdate(), INTERVAL 2 MONTH) - INTERVAL (a.a + (10 * b.a) ) DAY as Date
FROM (select 0 as a 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) as a
CROSS JOIN (select 0 as a 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) as b
) all_dates
LEFT OUTER JOIN reports r
ON all_dates.Date = r.tracked_on
AND domain_id = 1
WHERE all_dates.Date BETWEEN '2014-09-01' AND '2014-09-30'
GROUP BY
the_date
ORDER BY
the_date ASC;
我还通过使用
DATE_ADD()
将起点推向未来,我已经缩小了它的尺寸。这两个都是选项,可以根据需要进行调整。
Demo at SQLfiddle
要获得每一行的domain_id(如问题中所示),您需要使用以下内容:;注意,您可以使用
IFNULL()
这是MySQL特有的,但我使用过
COALESCE()
这是更通用的SQL。然而,这里显示的@参数的使用是MySQL特有的。
SET @domain := 1;
SELECT
COUNT(r.domain_id)
, all_dates.Date AS the_date
, coalesce(domain_id,@domain) AS domain_id
FROM (
SELECT DATE_ADD(curdate(), INTERVAL 2 month) - INTERVAL (a.a + (10 * b.a) ) DAY as Date
FROM (select 0 as a 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) as a
CROSS JOIN (select 0 as a 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) as b
) all_dates
LEFT JOIN reports r
ON all_dates.Date = r.tracked_on
AND domain_id = @domain
WHERE all_dates.Date BETWEEN '2014-09-01' AND '2014-09-30'
GROUP BY
the_date
ORDER BY
the_date ASC;
See this at SQLfiddle