简体   繁体   English

计算 PostgreSQL 中的帐户余额历史记录

[英]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]

Demo on dbfiddle dbfiddle 上的演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM