Подтвердить что ты не робот

Вычисление суммарной суммы в 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.

Может ли кто-нибудь предложить, как добиться этого результата?

4b9b3361

Ответ 1

В принципе, вам нужна функция окна здесь. Это стандартная функция в наши дни. В дополнение к подлинным функциям окна вы можете использовать любую агрегированную функцию как функцию окна в Postgres, добавив предложение OVER.

Особая трудность здесь заключается в том, чтобы правильно получить разделы и порядок сортировки:

SELECT ea_month, id, amount, ea_year, circle_id
     , sum(amount) OVER (PARTITION BY circle_id ORDER BY 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 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;