Du skal generere alle de ønskede datoer, og derefter venstre forene dine data til datoerne. Bemærk også, at det er vigtigt at sætte nogle prædikater i venstre joins ON klausul og andre i WHERE klausul:
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
Hvordan fungerer ovenstående?
CROSS JOINopretter et kartesisk produkt mellem alle tilgængelige år og alle tilgængelige måneder. Dette er, hvad du vil have, du vil have kombinationer hele året om måneden uden huller.LEFT JOINtilføjer allequalitaetposter til resultatet (hvis de findes) og føjer dem til det kartesiske års-månedsprodukt fra før. Det er vigtigt at sætte prædikter somstatus = 1prædikat her.COUNT(created)tæller kun ikke-NULL værdier afcreated, dvs. nårLEFT JOINproducerer ingen rækker for en given år-måned, vi vil have0som et resultat, ikke1, dvs. vi ønsker ikke at tælleNULLværdi.
En bemærkning om ydeevne
Ovenstående gør stor brug af strengoperationer og aritmetik for dato og klokkeslæt i din ON og WHERE prædikater. Dette vil ikke fungere for mange data. I så fald bør du bedre forkorte og indeksere dine år-måneder i qualitaet tabel og kun arbejde på disse værdier.