PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Изчисляване на кумулативна сума в PostgreSQL

По принцип имате нужда от функция за прозорец. Това е стандартна функция в днешно време. В допълнение към оригиналните функции на прозореца, можете да използвате всякакви агрегатна функция като прозоречна функция в Postgres чрез добавяне на OVER клауза.

Специалната трудност тук е да получите дялове и да сортирате правилно:

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;

И не GROUP BY .

Сумата за всеки ред се изчислява от първия ред в дяла до текущия ред - или цитирайки ръководството, за да бъдем точни:

Опцията за рамкиране по подразбиране е RANGE UNBOUNDED PRECEDING , което е същото като RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW . СORDER BY , това задава рамката да бъде всички редове от началото на дяла до последния ORDER BY на текущия ред връстника .

... коя е кумулативната или текущата сума, която търсите. Удебелен акцент мое.

Редове със същия (circle_id, ea_year, ea_month) са „връстници“ в тази заявка. Всички те показват една и съща текуща сума с всички партньори, добавени към сумата. Но предполагам, че вашата таблица е UNIQUE на (circle_id, ea_year, ea_month) , тогава редът на сортиране е детерминиран и нито един ред няма подобни.

Postgres 11 добави инструменти за включване/изключване на партньори с новия frame_exclusion настроики. Вижте:

  • Агрегиране на всички стойности, които не са в една и съща група

Сега, ORDER BY ... ea_month няма да работи с низове за имена на месеци . Postgres ще сортира по азбучен ред според настройката на локала.

Ако имате действителна date стойности, съхранени във вашата таблица, можете да сортирате правилно. Ако не, предлагам да замените ea_year и ea_month с една колона mon от тип date във вашата маса.

  • Трансформирайте това, което имате с to_date() :

      to_date(ea_year || ea_month , 'YYYYMonth') AS mon
    
  • За показване можете да получите оригинални низове с to_char() :

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

Докато остана с лошия дизайн, това ще работи:

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. Преглед на методите JOIN в PostgreSQL

  2. Интегриране на PostgreSQL със системи за удостоверяване

  3. Как да внедрите високодостъпен PostgreSQL с единична крайна точка за WordPress

  4. Каква е разликата между `->>` и `->` в Postgres SQL?

  5. org.postgresql.util.PSQLException:Големите обекти не може да се използват в режим на автоматично записване