Я хочу найти совокупное или текущее количество поля и вставить его из промежуточной таблицы в таблицу. Моя промежуточная структура выглядит примерно так:
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.
Может ли кто-нибудь подсказать, как достичь этого результата?
Ответы:
По сути, вам нужна оконная функция . В настоящее время это стандартная функция. Помимо настоящих оконных функций, вы можете использовать любую агрегатную функцию в качестве оконной функции в 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
.Сумма для каждой строки рассчитывается от первой строки в разделе до текущей строки - или, если быть точным, цитируя руководство :
... которая представляет собой накопительную или текущую сумму, которую вы ищете. Смелый акцент мой.
Строки с одинаковыми значениями
(circle_id, ea_year, ea_month)
являются «одноранговыми» в этом запросе. Все они показывают одну и ту же текущую сумму со всеми равноправными участниками, добавленными к сумме. Но я предполагаю, что ваш столUNIQUE
включен(circle_id, ea_year, ea_month)
, тогда порядок сортировки детерминирован и ни одна строка не имеет сверстников.Теперь
ORDER BY ... ea_month
не будет работать со строками для названий месяцев . Postgres будет выполнять сортировку в алфавитном порядке в соответствии с настройками локали.Если у вас есть фактические
date
значения, хранящиеся в вашей таблице, вы можете правильно отсортировать их. Если нет, я предлагаю заменитьea_year
иea_month
одним столбцомmon
типаdate
в вашей таблице.Преобразуйте то, что у вас есть
to_date()
:Для отображения можно получить оригинальные строки с помощью
to_char()
:Несмотря на неудачный дизайн, это будет работать:
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;
источник
range unbounded preceding
совпадает сrange between unbounded preceding and current row
. Вот почемуsum()
при использовании в качестве оконной функции выдает промежуточную сумму - в то время как другие оконные функции не имеют этого фрейма по умолчанию.PARTITION
не всегда требуется для создания