【问题标题】:Join query to count the number of records isn't counting right加入查询以计算记录数不正确
【发布时间】:2011-12-10 01:54:59
【问题描述】:

我有一个类别表,其工作方式类似于 StackOverflow 上的标签。有一些类别,例如 JavaScript,它将是一个顶级类别,也许 jQuery 将是 JavaScript 的一个子类别。

我要查询的是每个类别下有多少条记录(在我的应用程序中它们是“问题”)。

这是我到目前为止的 SQL。 question_categories 只是一个连接表,它有一个problem_id 和一个category_id。

select problems.problem_id , categories.category_id , category_name , count(problems.problem_id) as num_problems , is_top
from problems 
    left join problem_categories on
    problems.problem_id = problem_categories.category_id
    left join categories on
    problem_categories.category_id = categories.category_id
    where is_top = 1;

这只会返回一行。我希望返回 is_top = 1 的记录数(这意味着它是顶级类别)。

我怎样才能改变我的查询来做到这一点?

谢谢!!

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    不用猜逻辑,错在需要GROUP BY才能算:

    SELECT problems.problem_id, categories.category_id, category_name, 
    COUNT(problems.problem_id) as num_problems, is_top
    FROM problems 
    LEFT JOIN problem_categories 
    ON problems.problem_id = problem_categories.category_id
    LEFT JOIN categories 
    ON problem_categories.category_id = categories.category_id
    WHERE is_top = 1;
    GROUP BY  problems.problem_id, categories.category_id, category_name
    

    但是,如果您想要每个顶级类别的问题数量,您的逻辑可能会变成这样:

    SELECT category_name, categories.category_id, problems.problem_id, 
    COUNT(problems.problem_id) as num_problems
    FROM categories 
    JOIN problem_categories 
    ON problem_categories.category_id = categories.category_id
    JOIN problems 
    ON problems.problem_id = problem_categories.category_id
    WHERE is_top = 1;
    GROUP BY category_name, categories.category_id, problems.problem_id
    

    注意:

    • 对于每个类别,您都会遇到问题,然后计算这些问题
    • 您使用 JOIN 而不是 LEFT JOIN,因为您不关心无论如何都没有问题的类别。
    • 您可以将 is_top 排除在选择之外,因为无论如何您都将它放在了 WHERE 子句中。选择不在您的 GROUP BY 中的东西会得到任何随机值,但由于所有值都是 1,您可以放心地选择,或者直接离开。

    【讨论】:

      【解决方案2】:

      “这仅返回一行。我希望返回 is_top = 1 的记录数(这意味着它是顶级类别)。”我怀疑这就是你得到的。

      ...count(problems.problem_id) as num_problems...
      ...where is_top = 1;
      

      我认为您需要在您的一个或多个字段中引入GROUP BY 子句

      【讨论】:

        【解决方案3】:

        您的查询中有一些问题:

        1. 如其他答案所述,查询缺少 GROUP BY 子句

        2. 查询中的第一个 JOIN 匹配不相关的列 - “on questions.problem_id = problem_categories.category_id”。如您所见,它将problem_id 与category_id 结合在一起

        3. 虽然这可能不是当前数据集的问题,但要获取每个类别的计数,将categories 表保留在 LEFT JOIN 的最左侧会更有意义
        4. 从优化的角度来看,我认为您不需要将 problems 表放入查询中,因为该表中没有输出需要的任何内容

        请在您的查询的另一个版本下方:

        SELECT `categories`.`category_id`, `categories`.`category_name`, COUNT(`problem_categories`.`problem_id`) AS `num_problems`, `categories`.`is_top`
        FROM `categories`
        LEFT JOIN `problem_categories` ON `problem_categories`.`category_id` = `categories`.`category_id`
        WHERE `categories`.`is_top` = 1
        GROUP BY `categories`.`category_id`;
        

        希望以上内容有所帮助!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-02-26
          • 1970-01-01
          • 1970-01-01
          • 2020-11-19
          • 2016-10-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多