Bạn cần một OUTER JOIN
để đến mỗi ngày từ đầu đến cuối bởi vì nếu bạn sử dụng INNER JOIN
nó sẽ giới hạn đầu ra chỉ với những ngày được kết hợp (tức là chỉ những ngày đó trong bảng báo cáo).
Ngoài ra, khi bạn sử dụng OUTER JOIN
bạn phải quan tâm đến các điều kiện trong mệnh đề where clause
không gây ra implicit inner join
; ví dụ AND domain_id =1 nếu sử dụng trong mệnh đề where sẽ loại bỏ bất kỳ hàng nào không đáp ứng điều kiện đó, nhưng khi được sử dụng làm điều kiện nối, nó chỉ hạn chế các hàng của bảng báo cáo.
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;
Tôi cũng đã thay đổi bảng dẫn xuất all_dates, bằng cách sử dụng DATE_ADD()
để thúc đẩy điểm xuất phát trong tương lai, và tôi đã giảm kích thước của nó. Cả hai đều là các tùy chọn và có thể được điều chỉnh khi bạn thấy phù hợp.
để đến domain_id cho mọi hàng (như được hiển thị trong câu hỏi của bạn), bạn sẽ cần sử dụng một số cách như sau; Lưu ý rằng bạn có thể sử dụng IFNULL()
là MySQL cụ thể nhưng tôi đã sử dụng COALESCE()
là SQL chung chung hơn. Tuy nhiên, dù sao thì việc sử dụng @parameter như được hiển thị ở đây cũng là dành riêng cho 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;