Вычисление кумулятивной суммы в 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 BY
peer.
... это совокупная или текущая сумма, которую вы ищете. Смелый акцент мой.
строки с тем же (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;