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 JOINcré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 JOINajoute tous lesqualitaetenregistrements 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 = 1prédicat ici.COUNT(created)ne compte que les valeurs non NULL decreated, c'est-à-dire lorsque leLEFT JOINne produit aucune ligne pour une année-mois donnée, nous voulons0par conséquent, pas1, c'est-à-dire que nous ne voulons pas compter leNULLvaleur.
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.