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 JOIN
opretter 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 JOIN
tilføjer allequalitaet
poster 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 = 1
prædikat her.COUNT(created)
tæller kun ikke-NULL værdier afcreated
, dvs. nårLEFT JOIN
producerer ingen rækker for en given år-måned, vi vil have0
som et resultat, ikke1
, dvs. vi ønsker ikke at tælleNULL
væ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.