Musisz wygenerować wszystkie poszukiwane daty, a następnie pozostawić dołączyć swoje dane do dat. Zauważ również, że ważne jest, aby umieścić kilka predykatów w ON
lewego sprzężenia i inne w WHERE
klauzula:
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
Jak to działa?
CROSS JOIN
tworzy produkt kartezjański pomiędzy wszystkimi dostępnymi latami i wszystkimi dostępnymi miesiącami. To jest to, czego chcesz, chcesz wszystkich kombinacji rocznych bez przerw.LEFT JOIN
dodaje wszystkiequalitaet
rekordy do wyniku (jeśli istnieją) i dołącza je do produktu kartezjańskiego rok-miesiąc sprzed. Ważne jest, aby umieścić predykaty, takie jakstatus = 1
orzeczenie tutaj.COUNT(created)
zlicza tylko wartości inne niż NULL zcreated
, czyli gdyLEFT JOIN
nie generuje wierszy dla danego roku-miesiąca, chcemy0
w rezultacie, a nie1
, czyli nie chcemy liczyćNULL
wartość.
Uwaga na temat wydajności
Powyższe w dużym stopniu wykorzystuje operacje na ciągach i arytmetykę daty i czasu w twoim ON
i WHERE
predykaty. To nie zadziała w przypadku dużej ilości danych. W takim przypadku powinieneś lepiej wstępnie obciąć i zaindeksować swoje roczne miesiące w qualitaet
tabeli i operuj tylko na tych wartościach.