Bạn cần tạo tất cả các ngày mong muốn, sau đó kết hợp dữ liệu của bạn với các ngày. Cũng lưu ý rằng điều quan trọng là phải đặt một số vị từ trong ON
của phép nối bên trái và các mệnh đề khác trong WHERE
mệnh đề:
SELECT
CONCAT(y, '-', LPAD(m, 2, '0')) as byMonth,
COUNT(`created`) AS Total
FROM (
SELECT year(now()) AS y UNION ALL
SELECT year(now()) - 1 AS y
) `years`
CROSS JOIN (
SELECT 1 AS m UNION ALL
SELECT 2 AS m UNION ALL
SELECT 3 AS m UNION ALL
SELECT 4 AS m UNION ALL
SELECT 5 AS m UNION ALL
SELECT 6 AS m UNION ALL
SELECT 7 AS m UNION ALL
SELECT 8 AS m UNION ALL
SELECT 9 AS m UNION ALL
SELECT 10 AS m UNION ALL
SELECT 11 AS m UNION ALL
SELECT 12 AS m
) `months`
LEFT JOIN `qualitaet` q
ON YEAR(`created`) = y
AND MONTH(`created`) = m
AND `status` = 1
WHERE STR_TO_DATE(CONCAT(y, '-', m, '-01'), '%Y-%m-%d')
>= MAKEDATE(year(now()-interval 1 year),1) + interval 5 month
AND STR_TO_DATE(CONCAT(y, '-', m, '-01'), '%Y-%m-%d')
<= now()
GROUP BY y, m
ORDER BY y, m
Ở trên hoạt động như thế nào?
-
CROSS JOIN
tạo sản phẩm cartesian giữa tất cả các năm có sẵn và tất cả các tháng có sẵn. Đây là những gì bạn muốn, bạn muốn kết hợp tất cả các tháng trong năm không có khoảng cách. -
LEFT JOIN
thêm tất cảqualitaet
ghi vào kết quả (nếu chúng tồn tại) và kết hợp chúng với sản phẩm cartesian năm tháng từ trước đó. Điều quan trọng là đặt các dự đoán nhưstatus = 1
vị ngữ ở đây. -
COUNT(created)
chỉ đếm các giá trị không phải NULL củacreated
, tức là khiLEFT JOIN
không tạo ra hàng nào cho bất kỳ tháng nào trong năm nhất định, chúng tôi muốn0
do đó, không phải1
, tức là chúng tôi không muốn đếmNULL
giá trị.
Lưu ý về hiệu suất
Phần trên sử dụng nhiều các phép toán chuỗi và số học ngày giờ trong ON
của bạn và WHERE
các vị ngữ. Điều này sẽ không hoạt động đối với nhiều dữ liệu. Trong trường hợp đó, tốt hơn bạn nên cắt bớt trước và lập chỉ mục các tháng trong năm của mình trong qualitaet
và chỉ hoạt động trên các giá trị đó.