Ответ 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;