Вычисление кумулятивной суммы в 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;