Solución adecuada
SELECT *
FROM (
SELECT day::date
FROM generate_series(timestamp '2007-12-01'
, timestamp '2008-12-01'
, interval '1 month') day
) d
LEFT JOIN (
SELECT date_trunc('month', date_col)::date AS day
, count(*) AS some_count
FROM tbl
WHERE date_col >= date '2007-12-01'
AND date_col <= date '2008-12-06'
-- AND ... more conditions
GROUP BY 1
) t USING (day)
ORDER BY day;
-
Usa
LEFT JOIN, por supuesto. -
generate_series()puede producir una tabla de marcas de tiempo sobre la marcha, y muy rápido. -
Por lo general, es más rápido agregar antes Tú te unes. Recientemente proporcioné un caso de prueba en sqlfiddle.com en esta respuesta relacionada:
- PostgreSQL:ordenar por matriz
-
Enviar la
timestampadate(::date) para un formato básico. Para más usoto_char(). -
GROUP BY 1es una forma abreviada de sintaxis para hacer referencia a la primera columna de salida. Podría serGROUP BY daytambién, pero eso podría entrar en conflicto con una columna existente del mismo nombre. OGROUP BY date_trunc('month', date_col)::datepero eso es demasiado largo para mi gusto. -
Funciona con los argumentos de intervalo disponibles para
date_trunc(). -
count()nunca produceNULL(0sin filas), pero elLEFT JOINlo hace.
Para devolver0en lugar deNULLen el exteriorSELECT, usaCOALESCE(some_count, 0) AS some_count. El manual. -
Para una solución más genérica o intervalos de tiempo arbitrarios considere esta respuesta estrechamente relacionada:
- La mejor manera de contar registros por intervalos de tiempo arbitrarios en Rails+Postgres