【问题标题】:MYSQL GROUP BY LEFT JOIN and COUNTMYSQL GROUP BY LEFT JOIN 和 COUNT
【发布时间】:2020-05-17 01:42:49
【问题描述】:

我在使用 JOIN 子句对 MYSQL 数据库中的项目进行分组和计数时遇到问题

我的两张表如下

用户表

id | surname | othernames
1  |  Doe    | John
2  |  Doe    | Jane
3  |  Doe    | Mary

订阅表

id | user_id | parent_subscription_id 
1  | 1       | Null
2  | 2       | 1
3  | 3       | 1
4  | 4       | 2                         
5  | 5       | 3
6  | 6       | 3

我需要能够生成如下列表

Name         |   Referrals
John Doe     | 2
Jane Doe     | 1
Mary Doe     | 2

换句话说,它是用户表中的用户,其 users.id 与 subscriptions.user_id 匹配,其订阅的订阅 id 是另一个订阅的父订阅。这意味着,如果您的订阅被另一个订阅引用为其自己的 parent_subscription_id,那么该新订阅将成为您的推荐。

我尝试了以下查询,但它没有给我预期的结果

SELECT users.surname, users.othernames,count('s.parent_subscription_id') as referrals 
FROM users 
    LEFT JOIN subscriptions s ON s.user_id=users.id 
group BY parent_subscription_id

我已经检查了一些关于 SO 的其他问题,但我找不到任何可以解决此类问题的问题 谢谢

【问题讨论】:

  • 我不清楚你想要得到什么结果。 John Doe 如何有 2 个推荐人?是不是把他的user_id关联的subscription.id当成两条记录的subscription.parent_subscription_id了?
  • @Moob,是的。它是 users 表中 users.id 与 subscriptions.user_id 匹配的用户,该用户的订阅是父订阅。换句话说,如果您的订阅被另一个订阅引用为其自己的 parent_subscription_id,那么该新订阅将成为您的推荐
  • 它已从问题中删除,但这是一个与 OP 架构匹配的 sqlFiddle
  • 请将您的问题所需的所有内容以文本形式放在您的帖子中,而不仅仅是其他地方。请通过编辑而不是 cmets 进行澄清。 How to Ask“它没有给我预期的结果”对于错误,minimal reproducible example 应该包含您可以提供的最少代码,即您显示的代码可以通过您显示的代码扩展为不正常。 (调试基础。)当你得到一个你不期望的结果时,停止试图找到你的总体目标并找出你的误解是什么。--隔离第一个意外的子表达式及其输入和输出。 (调试基础。)
  • 这个不清楚。使用足够多的单词、句子和对部分示例的引用来清楚完整地表达你的意思。一个“基本上”或“基本上”或“换句话说”,它没有介绍或总结你也给出的清晰、准确和完整的描述,只是意味着“不清楚”。在给出业务关系(船舶)/关联或表(基础或查询结果)时,说明其中的一行根据其列值说明了业务情况。

标签: mysql group-by count left-join


【解决方案1】:

我认为你想要的逻辑是:

select u.surname, u.othernames, count(s.parent_subscription_id) referrals
from subscriptions s
left join subscriptions p on p.id = s.parent_subscription_id
inner join users u on u.id = coalesce(p.user_id, s.user_id)
group by u.id, u.surname, u.othernames

Demo on DB Fiddle

姓氏 |其他名字 |转介 :-------- | :--------- | --------: 能源部 |约翰 | 2 能源部 |简 | 1 能源部 |玛丽 | 2

【讨论】:

  • 这带来了几乎如预期的结果,但我似乎遇到的唯一问题是它似乎没有捕获所有用户。我有 99 个用户,但结果显示 45 条记录,因此缺少某些用户的记录订阅推荐。我期待它为那些没有推荐的人显示 0。可以对其进行调整吗?
【解决方案2】:

您可以在用户表之间使用连接并选择计算计数为:

SELECT 
    -- Get all users
    users.surname, 
    users.othernames,
    IFNULL(reff.cnt, 0) as referrals -- Preset 0 for users have not referrals in joined table
FROM users
-- Join calculation result
LEFT JOIN (
    -- Calculate count by user
    SELECT parent_subscription_id, COUNT(*) AS cnt
    FROM subscriptions
    GROUP BY subscriptions.parent_subscription_id
) reff on reff.parent_subscription_id = users.id;

【讨论】:

  • 这对引导我走上正确的道路非常有帮助。应用 IFNULL(count,0) 帮助我了解了哪里出错了。太感谢了。 +1
【解决方案3】:

使用users.surname, users.othernames更改按字段分组

SELECT users.surname, users.othernames,count(s.parent_subscription_id) as referrals 
FROM users 
    LEFT JOIN subscriptions s ON s.user_id=users.id 
group BY users.surname, users.othernames

【讨论】:

  • 使用count(s.parent_subscription_id) 而不是count('s.parent_subscription_id')。否则,它将被视为字符串并产生不正确的结果(将包含空值)。
  • 我不认为这给出了 OP 期望的结果。在我看来,推荐的计数应该基于用户的subscription.id 在subscription.parent_subscription_id 中使用的记录数。例如,parent_subscription_id 1 用于 2 条记录,该订阅的所有者是用户 1 (John)。
【解决方案4】:

您需要按用户表的 id 分组,因为您需要获取每个用户的计数,这是您的主表是用户。试试这样。

SELECT users.surname, users.othernames, count('s.parent_subscription_id') as referrals 
FROM users 
LEFT JOIN subscriptions s ON s.user_id = users.id 
group BY users.id

【讨论】:

    【解决方案5】:

    这个查询最终给了我一直在寻找的结果

    SELECT u.surname,u.othernames,s1.id,s1.parent_subscription_id, 
    s1.refcode, IFNULL(count(s2.parent_subscription_id),0) as referrals 
    FROM `subscriptions` s1 left join subscriptions s2 
    on s1.id=s2.parent_subscription_id 
    LEFT JOIN users u ON u.id=s1.user_id
    GROUP by s1.id
    

    感谢大家对此的指导和支持。我非常感谢它

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多