PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Obliczanie sumy skumulowanej w PostgreSQL

Zasadniczo potrzebujesz funkcji okna. To obecnie standardowa funkcja. Oprócz oryginalnych funkcji okien możesz używać dowolnych funkcja agregująca jako funkcja okna w Postgresie przez dodanie OVER klauzula.

Szczególna trudność polega na tym, aby uzyskać właściwe partycje i porządek sortowania:

SELECT ea_month, id, amount, ea_year, circle_id
     , sum(amount) OVER (PARTITION BY circle_id
                         ORDER BY ea_year, ea_month) AS cum_amt
FROM   tbl
ORDER  BY circle_id, month;

I nie GROUP BY .

Suma dla każdego wiersza jest obliczana od pierwszego wiersza w partycji do bieżącego wiersza - lub cytując instrukcję, aby być precyzyjnym:

Domyślną opcją kadrowania jest RANGE UNBOUNDED PRECEDING , który jest taki sam jak RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW . ZORDER BY , ustawia to ramkę na wszystkie wiersze od partycjistart do ostatniego ORDER BY bieżącego wiersza równorzędny .

... czyli suma skumulowana lub bieżąca, której szukasz. Pogrubiony nacisk na moje.

Wiersze z tym samym (circle_id, ea_year, ea_month)"rówieśnikami" w tym zapytaniu. Wszystkie z nich pokazują tę samą sumę bieżącą ze wszystkimi rówieśnikami dodanymi do sumy. Ale zakładam, że twoja tabela jest UNIQUE w (circle_id, ea_year, ea_month) , porządek sortowania jest deterministyczny i żaden wiersz nie ma równorzędnych pozycji.

Postgres 11 dodał narzędzia do włączania / wykluczania peerów z nowym frame_exclusion opcje. Zobacz:

  • Agregacja wszystkich wartości spoza tej samej grupy

Teraz ORDER BY ... ea_month nie będzie działać z ciągami znaków dla nazw miesięcy . Postgres posortowałby alfabetycznie zgodnie z ustawieniami regionalnymi.

Jeśli masz aktualną date wartości przechowywane w tabeli można poprawnie posortować. Jeśli nie, sugeruję zastąpienie ea_year i ea_month z pojedynczą kolumną mon typu date w twoim stole.

  • Przekształć to, co masz za pomocą to_date() :

      to_date(ea_year || ea_month , 'YYYYMonth') AS mon
    
  • Do wyświetlania możesz uzyskać oryginalne ciągi za pomocą to_char() :

      to_char(mon, 'Month') AS ea_month
      to_char(mon, 'YYYY') AS ea_year
    

Jeśli utknąłeś z niefortunnym projektem, to zadziała:

SELECT ea_month, id, amount, ea_year, circle_id
     , sum(amount) OVER (PARTITION BY circle_id ORDER BY mon) AS cum_amt
FROM   (SELECT *, to_date(ea_year || ea_month, 'YYYYMonth') AS mon FROM tbl)
ORDER  BY circle_id, mon;



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak zoptymalizować replikację logiczną PostgreSQL

  2. przenoszenie danych z jednej tabeli do drugiej, edycja postgresql

  3. Czy usunięcie bazy danych nie musi odbywać się w żadnej transakcji?

  4. Konwertuj django RawQuerySet na Queryset

  5. PostgreSQL jak połączyć wartość interwału '2 dni'