Esto es muy similar a otras preguntas, pero la mejor consulta sigue siendo complicada.
Consulta básica para obtener la suma acumulada rápidamente:
SELECT to_char(date_trunc('month', date_added), 'Mon YYYY') AS mon_text
, sum(sum(qty)) OVER (ORDER BY date_trunc('month', date_added)) AS running_sum
FROM tbl
GROUP BY date_trunc('month', date_added)
ORDER BY date_trunc('month', date_added);
La parte complicada es rellenar los meses que faltan :
WITH cte AS (
SELECT date_trunc('month', date_added) AS mon, sum(qty) AS mon_sum
FROM tbl
GROUP BY 1
)
SELECT to_char(mon, 'Mon YYYY') AS mon_text
, sum(c.mon_sum) OVER (ORDER BY mon) AS running_sum
FROM (SELECT min(mon) AS min_mon FROM cte) init
, generate_series(init.min_mon, now(), interval '1 month') mon
LEFT JOIN cte c USING (mon)
ORDER BY mon;
El implícito CROSS JOIN LATERAL
requiere Postgres 9.3+. Esto comienza con el primer mes en la tabla.
Para comenzar con un mes determinado :
WITH cte AS (
SELECT date_trunc('month', date_added) AS mon, sum(qty) AS mon_sum
FROM tbl
GROUP BY 1
)
SELECT to_char(mon, 'Mon YYYY') AS mon_text
, COALESCE(sum(c.mon_sum) OVER (ORDER BY mon), 0) AS running_sum
FROM generate_series('2015-01-01'::date, now(), interval '1 month') mon
LEFT JOIN cte c USING (mon)
ORDER BY mon;
Separación de meses de diferentes años. No lo pediste, pero lo más probable es que lo quieras.
Tenga en cuenta que el "mes" hasta cierto punto depende de la configuración de la zona horaria de la sesión actual. Detalles:
Relacionado:
- Calcular la suma acumulativa en PostgreSQL
- PostgreSQL:conteo continuo de filas para una consulta 'por minuto'
- Función de ventana de Postgres y agrupar por excepción