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 JOINtạ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 JOINthêm tất cảqualitaetghi 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 = 1vị ngữ ở đây. -
COUNT(created)chỉ đếm các giá trị không phải NULL củacreated, tức là khiLEFT JOINkhô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ốn0do đó, không phải1, tức là chúng tôi không muốn đếmNULLgiá 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ị đó.