Isso é muito semelhante a outras perguntas, mas a melhor consulta ainda é complicada.
Consulta básica para obter a soma corrente rapidamente:
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);
A parte complicada é preencher os meses que faltam :
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;
O
CROSS JOIN LATERAL
implícito
requer Postgres 9.3+. Isso começa com o primeiro mês na tabela.Para começar com um determinado mês :
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;
SQL Fiddle.
Mantendo meses de anos diferentes separados. Você não pediu isso, mas provavelmente vai querer.
Observe que o "mês" até certo ponto depende da configuração do fuso horário da sessão atual! Detalhes:
Relacionado:
- Calculando a soma cumulativa no PostgreSQL
- PostgreSQL:contagem de linhas em execução para uma consulta 'por minuto'
- Função da janela Postgres e agrupar por exceção