sql >> Database >  >> RDS >> PostgreSQL

Cumulatieve som van waarden per maand, invullen voor ontbrekende maanden

Dit lijkt erg op andere vragen, maar de beste vraag is nog steeds lastig.

Basisvraag om snel de lopende som te krijgen:

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);

Het lastige is om ontbrekende maanden in te vullen :

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;

De impliciete CROSS JOIN LATERAL vereist Postgres 9.3+. Dit begint met de eerste maand in de tabel.
Om met een bepaalde maand te beginnen :

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.

Maanden van verschillende jaren uit elkaar houden. Je hebt daar niet om gevraagd, maar je zult het waarschijnlijk wel willen.

Merk op dat de "maand" tot op zekere hoogte afhangt van de tijdzone-instelling van de huidige sessie! Details:

Gerelateerd:




  1. Postgres:accounts samenvoegen tot één identiteit op gemeenschappelijk e-mailadres

  2. Wat is de beste manier om oude rijen doorlopend uit MySQL te verwijderen?

  3. Berichten van abonnees en eigen berichten van gebruikers weergeven

  4. JPA Criteria API:hoe de datum op te halen in mm/dd/jjjj-formaat