加入查询来计算记录数不正确

时间:2011-12-09 16:43:57

标签: mysql sql

我有一个类别表,有点像StackOverflow上的标签。有一些类别,如JavaScript,这将是一个顶级类别,也许jQuery将是JavaScript的子类别。

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

这是我到目前为止的SQL。 problem_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的记录数(这意味着它是一个顶级类别)。

如何更改查询以执行此操作?

谢谢!

3 个答案:

答案 0 :(得分: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保留在select之外,因为无论如何都要将它放在WHERE子句中。选择不在GROUP BY中的内容将获得任意随机值,但由于所有值均为1,您可以安全地执行此操作,或者只是保留它。

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:0)

您的查询中有一些不妥之处:

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

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

  3. 连接起来
  4. 虽然这可能不是当前数据集的问题,但是为了获得每个类别的计数,将categories表保留在LEFT JOIN的最左侧更有意义
  5. 从优化的角度来看,我认为您不需要在查询中放置problems表,因为输出中不需要该表中的任何内容
  6. 请在您的查询的另一个版本下面:

    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`;
    

    希望以上有所帮助!