我有三张桌子,付款,收入,用户。我尝试首先获得用于获取有关用户的收入和付款信息的用户ID。有了这个,我还与DISTINCT一起计算并减去它以获得CURRENT收益。问题是如果任何表没有输入示例支付表,所以我得到NULL而不是数字。我该怎么解决这个问题。我尝试过IFNULL但没有工作
我就是这样做的
SELECT SUM(DISTINCT user_earnings.amount) -
SUM(DISTINCT user_payouts.payout_amount) as total_earnings
FROM user, user_earnings, user_payouts
WHERE user.id = 103
and user_earnings.user_id = user.id
and user_payouts.user_id = user.id
编辑:我制作了当前的表格
user_earnings(问题仅在于user_id 103
id user_id amount
1 102 250
2 102 1000
3 101 5000
4 102 352
18 102 375
19 102 442
20 103 338 <-----
user_payouts
id user_id payout_amount
1 102 500
2 102 100
3 101 1000
用户
id payout_address
102 ***
103 ***
如您所见,付款没有关于user_id 103的条目,因为他从未付款。这就是为什么我得到null(我认为)
答案 0 :(得分:1)
<强>注1:强> 我肯定不会以这种方式使用Distinct ...如果将来的用户有338的另一个earn_amount,那么第二个338将不会被添加到总数中。
<强>注2:强> 请参阅我对COALESCE的使用而不是IFNULL。
<强>注3:强> 我更新了您的连接语法。请确认我保留了您的加入。
编辑:更新了答案,并为每个用户重复的earn_amounts帐户以及每位用户的重复payout_amounts提供了支持
查看小提琴,注意为用户103输入的重复内容(400 + 400 - 100 - 100))
SELECT (
COALESCE(ue.earned_amount,0) - COALESCE(up.payout_amount,0)
) AS total_earnings
FROM user u
JOIN (SELECT user_id, SUM(earned_amount) AS earned_amount
FROM Earned
GROUP BY user_id) ue
ON ue.user_id = u.id
JOIN (SELECT user_id, SUM(payout_amount) AS payout_amount
FROM Payouts
GROUP BY user_id) up
ON up.user_id = u.id
WHERE u.id = 103
效果说明:
如果您的获奖或奖金表预计会很大,那么性能改进的一些想法就会出现。
通过向每个查询添加Where子句来限制嵌套查询的返回结果集的大小,以便它们只返回user_id 103的结果。
为列user_id添加索引到已获奖和付款。
或者首先使用索引创建这些连接到临时表,然后将临时表连接到此查询
答案 1 :(得分:1)
试试这个:
SELECT u.id,
(SUM(DISTINCT ue.amount) -
COALESCE(SUM(DISTINCT up.payout_amount),0)) as total_earnings
FROM
user u
left outer join user_earnings ue on u.id = ue.user_id
left outer join user_payouts up on u.id = up.user_id
WHERE
u.id = 103;
抱歉,我没有对上述内容付出足够的努力。虽然它适用于一个小样本,但是当你过滤掉任何一个用户获得两笔相同数额的支出的实例时,上面会用更大的一组进行分解。
我认为这是你真正的解决方案:
SELECT
u.id,
(ue.earnings - up.payouts) as total_earnings
FROM
user u
inner join
(select distinct
u1.id,
SUM(COALESCE(ue.amount,0)) as earnings
from
user u1
left join user_earnings ue on u1.id = ue.user_id group by u1.id) ue on u.id = ue.id
inner join
(select distinct
u1.id,
SUM(COALESCE(up.payout_amount,0)) as payouts
from
user u1
left join user_payouts up on u1.id = up.user_id group by u1.id) up on u.id = up.id
WHERE
u.id = 103;
只是为了好玩,这是另一种选择,更短:
SELECT
u.id,
((select COALESCE(SUM(ue.amount),0) from user_earnings ue where ue.user_id = u.id) -
(select COALESCE(SUM(up.payout_amount),0) from user_payouts up where up.user_id = u.id)) as total_earnings
FROM
user u
WHERE
u.id = 103;
答案 2 :(得分:0)
您有3个问题 - DISTINCT
,JOIN
后跟GROUP BY
,未能处理NULL
。
SELECT u.id,
(
SELECT ( IFNULL(SUM(amount), 0)
FROM user_earnings WHERE user_id = u.id ) -
SELECT ( IFNULL(SUM(payout_amount), 0 )
FROM user_payouts WHERE user_id = u.id )
) as total_earnings
FROM user u
WHERE u.id = 103;
应解决所有问题。
DISTINCT
已经讨论过 - 给定用户可能存在重复值。JOIN
后跟GROUP BY
- 我称之为&#34; inflate-deflate syndrone&#34;。 JOIN
首先发生,从而使行数膨胀,然后GROUP BY
尝试补偿它。通常这是一个性能问题;在你的情况下,它也会破坏数据。NULL
,但我认为这个提法是正确的。这是一个罕见的&#39;子查询优于LEFT JOIN
的情况。它避免了SUM
的过度计算。 ghenghy的第一个解决方案可能与单 u.id
一样好;我应该为多个ID工作。