Devi generare tutte le date desiderate e poi unire i tuoi dati alle date. Nota anche che è importante inserire alcuni predicati nel ON
del join sinistro clausola e altri nel WHERE
clausola:
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
Come funziona quanto sopra?
CROSS JOIN
crea un prodotto cartesiano tra tutti gli anni disponibili e tutti i mesi disponibili. Questo è quello che vuoi, vuoi tutte le combinazioni anno-mese senza interruzioni.LEFT JOIN
aggiunge tutti iqualitaet
registra il risultato (se esistente) e li unisce al prodotto cartesiano anno-mese di prima. È importante inserire predittivi comestatus = 1
predicato qui.COUNT(created)
conta solo i valori non NULL dicreated
, ovvero quando ilLEFT JOIN
non produce righe per un dato anno-mese, vogliamo0
di conseguenza, non1
, cioè non vogliamo contare ilNULL
valore.
Una nota sulla performance
Quanto sopra fa un uso massiccio delle operazioni sulle stringhe e dell'aritmetica della data e dell'ora nel tuo ON
e WHERE
predicati. Questo non funzionerà per molti dati. In tal caso, dovresti pre-troncare e indicizzare meglio i tuoi anni-mesi nel qualitaet
tabella e operare solo su quei valori.