Вычисление кумулятивной суммы в PostgreSQL
Я хочу найти кумулятивный или рабочий объем поля и вставить его из промежуточного в таблицу. Моя промежуточная структура выглядит примерно так:
ea_month id amount ea_year circle_id
April 92570 1000 2014 1
April 92571 3000 2014 2
April 92572 2000 2014 3
March 92573 3000 2014 1
March 92574 2500 2014 2
March 92575 3750 2014 3
February 92576 2000 2014 1
February 92577 2500 2014 2
February 92578 1450 2014 3
Я хочу, чтобы моя целевая таблица выглядела примерно так:
ea_month id amount ea_year circle_id cum_amt
February 92576 1000 2014 1 1000
March 92573 3000 2014 1 4000
April 92570 2000 2014 1 6000
February 92577 3000 2014 2 3000
March 92574 2500 2014 2 5500
April 92571 3750 2014 2 9250
February 92578 2000 2014 3 2000
March 92575 2500 2014 3 4500
April 92572 1450 2014 3 5950
Я действительно очень смущен тем, как добиться этого результата. Я хочу достичь этого результата с помощью PostgreSQL.
может ли кто-нибудь предложить, как достичь этого результата?
1 ответов
в принципе, вам нужен функция окна здесь. Это стандартная функция в наши дни. В дополнение к подлинным функциям окна, вы можете использовать любой агрегатная функция как функция окна в 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 здесь.
сумма для каждой строки рассчитывается из первой строки в разделе к текущей строке-или quoting руководство если быть точным:
вариант кадрирования по умолчанию:
RANGE UNBOUNDED PRECEDING, который то же самое, чтоRANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. СORDER BY, это устанавливает кадр все строки из раздела запуск через последнюю строку текущей строкиORDER BYpeer.
... это совокупная или текущая сумма, которую вы ищете. Смелый акцент мой.
строки с тем же (circle_id, ea_year, ea_month) are "сверстники" в этом запросе. Все они показывают одинаковую текущую сумму со всеми сверстниками, добавленными к сумме. Но я предполагаю, что ваш стол UNIQUE on (circle_id, ea_year, ea_month), тогда порядок сортировки детерминирован, и ни одна строка не имеет сверстников.
теперь 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;