sql >> Base de Datos >  >> RDS >> Mysql

MySQL:recuento por mes (incluidos los registros faltantes)

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 los qualitaet registra al resultado (si existen) y los une al producto cartesiano año-mes anterior. Es importante poner predicados como el status = 1 predicado aquí.
  • COUNT(created) cuenta solo los valores no NULL de created , es decir, cuando LEFT JOIN no produce filas para ningún año-mes dado, queremos 0 como resultado, no 1 , es decir, no queremos contar el NULL 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.