U moet alle gewenste datums genereren en vervolgens uw gegevens bij de datums voegen. Merk ook op dat het belangrijk is om enkele predikaten in de ON
. van de linker join te plaatsen clausule, en andere in de WHERE
clausule:
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
Hoe werkt het bovenstaande?
CROSS JOIN
maakt een cartesiaans product tussen alle beschikbare jaren en alle beschikbare maanden. Dit is wat je wilt, je wilt alle jaar-maand combinaties zonder hiaten.LEFT JOIN
voegt allequalitaet
. toe records bij het resultaat (indien aanwezig) en voegt ze samen met het jaar-maand cartesiaanse product van voorheen. Het is belangrijk om prediacten te plaatsen zoals destatus = 1
predikaat hier.COUNT(created)
telt alleen niet-NULL-waarden vancreated
, d.w.z. wanneer deLEFT JOIN
produceert geen rijen voor een bepaalde jaar-maand, we willen0
als resultaat, niet1
, d.w.z. we willen deNULL
. niet tellen waarde.
Een opmerking over prestaties
Het bovenstaande maakt veel gebruik van tekenreeksbewerkingen en datum-tijdberekeningen in uw ON
en WHERE
predikaten. Dit gaat niet werken voor veel gegevens. In dat geval kunt u uw jaarmaanden beter vooraf inkorten en indexeren in de qualitaet
tabel, en werk alleen op die waarden.