[英]Calculate account balance history in PostgreSQL
I am trying to get a balance history on the account using SQL.我正在尝试使用 SQL 获取帐户的余额历史记录。 My table in PostgreSQL looks like this:
我在PostgreSQL中的表如下所示:
id sender_id recipient_id amount_money
--- ----------- ---------------------- -----------------
1 1 2 60.00
2 1 2 15.00
3 2 1 35.00
so the user with id number 2 currently has 40 dollars in his account.所以 ID 号为 2 的用户目前在他的帐户中有 40 美元。 I would like to get this result using sql:
我想使用 sql 得到这个结果:
[60, 75, 40]
Is it possible to do something like this using sql in postgres?是否可以在 postgres 中使用 sql 做这样的事情?
To get a rolling balance, you can SUM
the amounts (up to and including the current row) based on whether the id
was the recipient or sender:要获得滚动余额,您可以根据
id
是收件人还是SUM
对金额(最多并包括当前行)求和:
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
Output: Output:
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
If you want an array, you can use array_agg
with the above query as a derived table:如果你想要一个数组,你可以使用
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
Output: Output:
[60,75,40]
Demo on dbfiddle dbfiddle 上的演示
If you want to be more sophisticated and support balances for multiple accounts, you need to split the initial data into account ids, adding when the id is the recipient and subtracting when the sender.如果您想更复杂并支持多个帐户的余额,则需要将初始数据拆分为帐户 id,当 id 为接收者时添加,当发送者时减去。 You can use
CTE
s to generate the appropriate data:您可以使用
CTE
生成适当的数据:
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
Output: Output:
account_id bal_array
1 [-60,-75,-40]
2 [60,75,40]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.