问题描述
**Here is my sample data:**
Users table:
+------------+--------------+-------------+
| user_id | user_name | credit |
+------------+--------------+-------------+
| 1 | Moustafa | 100 |
| 2 | Jonathan | 200 |
| 3 | Winston | 10000 |
| 4 | Luis | 800 |
+------------+--------------+-------------+
Transaction table:
+------------+------------+------------+----------+---------------+
| trans_id | paid_by | paid_to | amount | transacted_on |
+------------+------------+------------+----------+---------------+
| 1 | 1 | 3 | 400 | 2020-08-01 |
| 2 | 3 | 2 | 500 | 2020-08-02 |
| 3 | 2 | 1 | 200 | 2020-08-03 |
+------------+------------+------------+----------+---------------+
我必须在每个客户帐户中找到净额,并告诉交易后净额是否小于0 ;
结果表:
+------------+------------+------------+-----------------------+
| user_id | user_name | credit | credit_limit_breached |
+------------+------------+------------+-----------------------+
| 1 | Moustafa | -100 | Yes |
| 2 | Jonathan | 500 | No |
| 3 | Winston | 9900 | No |
| 4 | Luis | 800 | No |
我正在尝试以下代码:
select user_id,user_name,sum(users.credit + k.credit) credit,case
when ifnull((users.credit + k.credit),users.credit) < 0 then "Yes"
else "No"
end as credit_limit_breached
from users
left join (select id,sum(credit)credit
from (select paid_by as id,sum(-amount)credit from transaction group by id
union
select paid_to as id,sum(amount)credit from transaction group by id) tem
group by id) k
on k.id = users.user_id
它为Luis(他没有做任何交易)提供空值,所以出了什么问题。
解决方法
取消透视交易,然后加入并汇总:
select user_id,sum(credit) as credit,sum(debit) as debit
from ((select paid_to as user_id,sum(amount) as credit,0 as debit
from transactions t
group by paid_to
) union all
(select paid_from as user_id,sum(amount)
from transactions t
group by paid_from
)
) t
group by user_id;
然后加入以获得最终结果:
select u.*,u.credit + t.credit - u.debit,(case when u.credit + t.credit - u.debit < 0 then 'yes' else no' end)
from users u left join
(select user_id,sum(debit) as debit
from ((select paid_to as user_id,0 as debit
from transactions t
group by paid_to
) union all
(select paid_from as user_id,sum(amount)
from transactions t
group by paid_from
)
) t
group by user_id
) t
on t.user_id = u.user_id
,
您当前的查询非常接近。您可以使用coalesce()
为完全没有交易的用户分配默认值0
。另外,您也不需要(也不需要)外部查询中的sum()
:简单的添加就足够了。
所以:
select
u.user_id,u.user_name,u.credit + coalesce(k.credit,0) credit,case when u.credit < coalesce(k.credit,0) then 'Yes' else 'No' end as credit_limit_breached
from users u
left join (
select id,sum(credit) credit
from (
select paid_by as id,sum(-amount) credit from transaction group by id
union all
select paid_to as id,sum(amount) credit from transaction group by id
) t
group by id
) k on k.id = users.user_id
另一种方法是相关子查询:
select
x.*,case when credit < 0 then 'Yes' else 'No' end as credit_limit_breached
from (
select
u.user_id,u.credit + (
select coalesce(sum(case when u.user_id = t.paid_for then amount else - amount end),0)
from transaction t
where u.user_id in (t.paid_by,t.paid_for)
) as as credit
from users u
) x