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