42

Я хочу найти суммарную или текущую сумму поля и вставить его из этапа в таблицу. Моя структура постановка что-то вроде этого:Расчет суммарной суммы в 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

Как вы получаете cum_amount 1000 в целевой таблице? Для circle_id сумма кажется равной 2000. –

ответ

72

В принципе, вам нужен window function. Это стандартная функция в наши дни. В дополнение к подлинным функциям окна, вы можете использовать любую функцию как функцию окна в 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 здесь.

Сумма для каждой строки рассчитывается из первой строки раздела в текущей строке, которая является суммой или текущей суммой, которую вы используете. The manual:

вариант кадрирования по умолчанию RANGE UNBOUNDED PRECEDING, который является же, как RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.

Теперь ORDER BY monthне будет работать только с натягивает для названий месяцев. Postgres будет сортировать по алфавиту в соответствии с настройкой локали. Если у вас есть фактические значения date, хранящиеся в вашей таблице, вы можете сортировать их правильно.

Если нет, предлагаю заменить ea_year и ea_month на одну колонку mon типа date в вашем столе.

  • Transform, что вы с 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; 
+0

Спасибо за решение .. Можете ли вы помочь мне с еще одной вещью. Я хочу реализовать ту же самую вещь, используя курсор с логикой, поскольку каждый круг будет иметь только одну запись за месяц в году. И функция должна запускаться один раз в месяц. Как я могу это достичь? –

+4

@YousufSultan: В большинстве случаев есть лучшее решение, чем курсор. Это определенно материал для нового вопроса. Пожалуйста, начните новый вопрос. –

+0

Я нахожу этот ответ неполным без хотя бы заметки о том, что здесь происходит «кадрирование», которое по умолчанию имеет «диапазон неограниченного предшествующего», который совпадает с «диапазоном между неограниченной предыдущей и текущей строкой». Вот почему 'sum()' при использовании в качестве функции окна создает текущую итоговую сумму, в то время как другие функции окна не имеют этого фрейма по умолчанию. –

 Смежные вопросы

  • Нет связанных вопросов^_^