Vous devez générer toutes les dates souhaitées, puis joindre vos données aux dates. Notez également qu'il est important de mettre des prédicats dans le ON
de la jointure gauche clause, et d'autres dans le WHERE
clause :
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
Comment fonctionne ce qui précède ?
CROSS JOIN
crée un produit cartésien entre toutes les années disponibles et tous les mois disponibles. C'est ce que vous voulez, vous voulez toutes les combinaisons année-mois sans interruption.LEFT JOIN
ajoute tous lesqualitaet
enregistrements au résultat (s'ils existent) et les joint au produit cartésien année-mois d'avant. Il est important de mettre des prédiactes comme lestatus = 1
prédicat ici.COUNT(created)
ne compte que les valeurs non NULL decreated
, c'est-à-dire lorsque leLEFT JOIN
ne produit aucune ligne pour une année-mois donnée, nous voulons0
par conséquent, pas1
, c'est-à-dire que nous ne voulons pas compter leNULL
valeur.
Remarque sur les performances
Ce qui précède fait un usage intensif des opérations de chaîne et de l'arithmétique date-heure dans votre ON
et WHERE
prédicats. Cela ne fonctionnera pas pour beaucoup de données. Dans ce cas, mieux vaut pré-tronquer et indexer vos années-mois dans le qualitaet
table et n'opèrent que sur ces valeurs.