Debe generar todas las fechas deseadas y luego dejar unir sus datos a las fechas. Tenga en cuenta también que es importante poner algunos predicados en ON
de la unión izquierda cláusula, y otras en el WHERE
cláusula:
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
¿Cómo funciona lo anterior?
CROSS JOIN
crea un producto cartesiano entre todos los años disponibles y todos los meses disponibles. Esto es lo que quiere, quiere todas las combinaciones año-mes sin espacios.LEFT JOIN
agrega todos losqualitaet
registra al resultado (si existen) y los une al producto cartesiano año-mes anterior. Es importante poner predicados como elstatus = 1
predicado aquí.COUNT(created)
cuenta solo los valores no NULL decreated
, es decir, cuandoLEFT JOIN
no produce filas para ningún año-mes dado, queremos0
como resultado, no1
, es decir, no queremos contar elNULL
valor.
Una nota sobre el rendimiento
Lo anterior hace un uso intensivo de las operaciones de cadena y la aritmética de fecha y hora en su ON
y WHERE
predicados. Esto no va a funcionar para una gran cantidad de datos. En ese caso, debería truncar previamente e indexar sus años-meses en el qualitaet
y opere solo con esos valores.