По принцип имате нужда от функция за прозорец. Това е стандартна функция в днешно време. В допълнение към оригиналните функции на прозореца, можете да използвате всякакви агрегатна функция като прозоречна функция в 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;