MYSQL 双重连接表和不准确 Counts/Sums

MYSQL Double Joining Tables and Inaccurate Counts/Sums

我正在尝试生成一份报告,显示顶级推荐人以及他们推荐的人产生了多少收入。

这是我的表格的缩写版本:

Users Table
------------------
id
referral_user_id (references another record in the users table)
username
firstname
lastname

Transactions Table
-------------------
id
user_id
amount

我试过使用以下查询:

SELECT 
    users.id, 
    users.firstname, 
    users.lastname, 
    users.username, 
    COUNT(referrals.id) referrals, 
    SUM(transactions.amount) income
FROM `users`
LEFT JOIN `users` AS `referrals` ON `users`.`id` = `referrals`.`referral_user_id`
LEFT JOIN `transactions` ON `referrals`.`id` = `transactions`.`user_id` 
GROUP BY `users`.`id`
ORDER BY `income` desc

我得到以下结果:

ID  |   username    |   Name    |   Referrals   |   Revenue From Referrals
----------------------------------------------------------------------------
1       jj              Jason       136             6536.30
2       jim             Jim         206             2957.75
3       tim             Tim         67              2712.10

唯一的问题是数字不相加。当我执行查询 SELECT COUNT(id) FROM users WHERE referral_user_id = 1 时,我得到的计数是 77,而当我执行 SELECT COUNT(id) FROM users WHERE referral_user_id = 2 时,我得到的计数是 161。

当我删除查询的 transaction/income 部分并执行此操作时:

SELECT 
    users.id, 
    users.firstname, 
    users.lastname, 
    users.username, 
    COUNT(referrals.id) referrals
FROM `users`
LEFT JOIN `users` AS `referrals` ON `users`.`id` = `referrals`.`referral_user_id`
GROUP BY `users`.`id`
ORDER BY `referrals` desc

我得到了正确的推荐计数。任何人都可以向我解释我错过了什么吗?

可能是您对聚合在 SQL 中的工作方式做出了错误的假设。

假设您像在没有 GROUP BY 和聚合的初始查询中那样加入,它可能会给出例如以下数据:

用户 1 与 [2,3] 链接,加入时有金额 [100,200] 导致我们有 4 条记录

ID  |   username    |   Name    |   referral_user_id    |   Amount
----------------------------------------------------------------------------
1       jj              Jason       2                       100
1       jj              Jason       3                       200
1       jj              Jason       3                       100
1       jj              Jason       2                       200

使用您的查询将对以上结果进行分组:

  • 导致计数 4 而不是 2
  • 总和为 600 而不是 300

请注意,输入 COUNT(referrals.id) 没有帮助,例如,COUNT(1) 会给出相同的结果。

对于推荐,您可以使用 COUNT(DISTINCT referrals.id),当且仅当您没有多次计算 a 和 b 之间的关系时。

否则,您应该使用子查询来解决这个问题。