Ceci est très similaire aux autres questions, mais la meilleure requête reste délicate.
Requête de base pour obtenir rapidement la somme cumulée :
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 partie délicate consiste à remplir les mois manquants :
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;
Le implicite CROSS JOIN LATERAL
nécessite Postgres 9.3+. Cela commence par le premier mois du tableau.
Pour commencer par un mois donné :
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;
Garder les mois de différentes années à part. Vous ne l'avez pas demandé, mais vous le voudrez probablement.
Notez que le "mois" dépend dans une certaine mesure du réglage du fuseau horaire de la session en cours ! Détails :
Connexe :
- Calcul de la somme cumulée dans PostgreSQL
- PostgreSQL :nombre de lignes en cours pour une requête 'par minute'
- Fonction de fenêtre Postgres et grouper par exception