[英]Calculate transaction balance in SQL
用戶表:
| user_id | user_name | credit |
| ------- | --------- | ------ |
| 1 | Winston | 100 |
| 2 | Moustafa | 600 |
| 3 | Jonathan | 800 |
| 4 | Maria | 100 |
交易表:
| trans_id | paid_by | paid_to | amount | transacted_on |
| -------- | ------- | ------- | ------ | ------------- |
| 1 | 2 | 4 | 1000 | 2020-08-28 |
| 2 | 3 | 2 | 600 | 2020-08-06 |
| 3 | 2 | 4 | 800 | 2020-08-15 |
| 4 | 1 | 3 | 800 | 2020-09-02 |
| 5 | 3 | 4 | 100 | 2020-08-02 |
| 6 | 3 | 4 | 500 | 2020-08-08 |
| 7 | 3 | 4 | 800 | 2020-09-17 |
我的代碼:
WITH tb1 AS (SELECT u.user_id, u.user_name, u.credit AS initial_amount,
SUM(t1.amount) AS credit_out, SUM(t2.amount) AS credit_in
FROM Users u
LEFT JOIN Transactions t1
ON u.user_id = t1.paid_by
LEFT JOIN Transactions t2
ON u.user_id = t2.paid_to
GROUP BY u.user_id),
tb2 AS (SELECT user_id, user_name,
(initial_amount - IFNULL(credit_out,0) + IFNULL(credit_in,0)) AS credit
FROM tb1)
SELECT user_id,user_name,credit,
CASE WHEN credit < 0 THEN 'Yes' ELSE 'No' END AS credit_limit_breached
FROM tb2
我的想法是首先根據paid_by和paid_to將Transaction表加入到Users中,並計算這些交易過程中的進出信用。 然后將 initial_amount、credit_in 和 credit_out 相加以獲得用戶帳戶中的最終信用。
我的輸出是:
| user_id | user_name | credit | credit_limit_breached |
| ------- | --------- | ------ | --------------------- |
| 1 | Winston | -700 | Yes |
| 2 | Moustafa | 0 | No |
| 3 | Jonathan | 2000 | No |
| 4 | Maria | 3300 | No |
預期的輸出是:
| user_id | user_name | credit | credit_limit_breached |
| ------- | --------- | ------ | --------------------- |
| 2 | Moustafa | -600 | Yes |
| 3 | Jonathan | -400 | Yes |
| 1 | Winston | -700 | Yes |
| 4 | Maria | 3300 | No |
我無法弄清楚我的代碼的哪一步是錯誤的,為什么我得到這些信用計算......
問題是關於join
。 如果分解第一個 CTE 查詢:
SELECT u.user_id, u.user_name, u.credit AS initial_amount, t1.amount AS credit_out, t2.amount AS credit_in
FROM Users u
LEFT JOIN Transactions t1
ON u.user_id = t1.paid_by
LEFT JOIN Transactions t2
ON u.user_id = t2.paid_to
WHERE u.user_id = 2
您在這里沒有得到一行,您得到的是具有重復值的 t1 x t2 行。 這就是提供不正確的SUM
結果的 beeing 聚合。 嘗試一個沒有 CTE 或額外連接的更簡單的查詢:
SELECT
overall.user_id,
Users.user_name,
SUM(overall.amount) as balance,
IF( SUM(overall.amount) < 0 , "Yes", "No") as credit_limit_breached
FROM(
SELECT outbount.paid_by as user_id, SUM(outbount.amount) * -1 as amount
FROM Transactions outbount
GROUP BY paid_by
UNION ALL
SELECT inbound.paid_to as user_id, SUM(inbound.amount) as amount
FROM Transactions inbound
GROUP BY paid_to
UNION ALL
SELECT initial.user_id as user_id, initial.credit as amount
FROM Users initial
) overall
LEFT JOIN Users
ON overall.user_id = Users.user_id
GROUP BY user_id
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.