Рассчитать историю баланса счета в PostgreSQL - PullRequest
0 голосов
/ 21 апреля 2020

Я пытаюсь получить историю баланса на счете, используя SQL. Моя таблица в PostgreSQL выглядит следующим образом:

   id  sender_id    recipient_id           amount_money
   --- -----------  ---------------------- -----------------
   1   1            2                      60.00
   2   1            2                      15.00
   3   2            1                      35.00

, поэтому у пользователя с идентификатором 2 в настоящее время есть 40 долларов на его счету. Я хотел бы получить этот результат, используя sql:

[60, 75, 40]

Можно ли сделать что-то подобное, используя sql в postgres?

1 Ответ

0 голосов
/ 21 апреля 2020

Чтобы получить скользящий баланс, вы можете SUM суммы (до текущей строки включительно), основанные на том, был ли id получателем или отправителем:

SELECT id, sender_id, recipient_id, amount_money,
       SUM(CASE WHEN recipient_id = 2 THEN amount_money
                WHEN sender_id = 2 THEN -amount_money
           END) OVER (ORDER BY id) AS balance
FROM transactions

Вывод:

id  sender_id   recipient_id    amount_money    balance
1   1           2               60.00           60.00
2   1           2               15.00           75.00
3   2           1               35.00           40.00

Если вам нужен массив, вы можете использовать array_agg с вышеуказанным запросом в качестве производной таблицы:

SELECT array_agg(balance)
FROM (
  SELECT SUM(CASE WHEN recipient_id = 2 THEN amount_money
                  WHEN sender_id = 2 THEN -amount_money
             END) OVER (ORDER BY id) AS balance
  FROM transactions
) t

Вывод:

[60,75,40]

Демонстрация на dbfiddle

Если вы хотите быть более сложным и поддерживать сальдо для нескольких учетных записей, вам нужно разделить исходные данные на идентификаторы учетных записей, добавив, когда идентификатор является получателем, и вычтя, когда отправитель. Вы можете использовать CTE s для генерации соответствующих данных:

WITH trans AS (
  SELECT id, sender_id AS account_id, -amount_money AS amount
  FROM transactions
  UNION ALL
  SELECT id, recipient_id AS account_id, amount_money AS amount
  FROM transactions
),
balances AS (
  SELECT id, account_id, ABS(amount),
         SUM(amount) OVER (PARTITION BY account_id ORDER BY id) AS balance
  FROM trans
)
SELECT account_id, ARRAY_AGG(balance) AS bal_array
FROM balances
GROUP BY account_id

Вывод:

account_id  bal_array
1           [-60,-75,-40]
2           [60,75,40]

Демонстрация на dbfiddle

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...