【发布时间】:2015-03-17 14:30:35
【问题描述】:
在应用程序中,有表 projects、categories 和一个表,用于处理它们之间的 n:m 关系 (project_category_info):
现在我想获取一个类别的所有项目(我正在使用HAVING 解决这个问题)。我还需要结果集中的信息,每个项目属于哪些类别(CONCAT_GROUP 结合GROUP):
SELECT
`projects`.*,
`categories`.`id` AS `id`,
GROUP_CONCAT(categories.id SEPARATOR '|||') AS `categories`,
GROUP_CONCAT(categories.short_name SEPARATOR '|||') AS `category_names`
FROM
`projects`
INNER JOIN
`project_category_info` ON `project_category_info`.`project_id` = `projects`.`id`
LEFT JOIN
`categories` ON `project_category_info`.`category_id` = `categories`.`id`
GROUP BY
`projects`.`id`
HAVING
(`categories`.`id` = 3)
;
结果集包含 13 行。但是当我省略GROUP_CONCAT 和GROUP 时,我会多得到一排。为什么?什么会导致这种行为?
【问题讨论】:
-
您能否提供一些显示SQL Fiddle? 中行为的示例数据另外,上述查询是错误的。您不能将
HAVING用于不使用任何聚合函数的条件。将该条件移至WHERE子句。也许这就是问题所在? -
这是一个糟糕的错误查询(两个错误,因为它有两个问题)。如果您的意图是在结果集中包含 category_id,那么它必须在您的 GROUP BY 子句中。任何其他 RDBMS 都会简单地出错,但 MySQL 很疯狂,所以它让你做这些废话(而且这是废话)。其次,使用 WHERE 子句而不是 HAVING。 HAVING 在聚合之后应用,并且由于您的聚合是无意义的(参见第 1 点),因此您的结果将是无意义的。
-
@McAdam331 非常感谢您的评论!我将
WHERE替换为HAVING以过滤分组后的数据。我不记得了,但WHERE有什么问题。现在我又用WHERE尝试了这个——它有效!请发表您的建议作为答案。 -
@JNevill 谢谢你的解释。实际上我不想在我的结果集中有一个
category_id,因为每个项目都属于多个类别。 -
@McAdam331 & @JNevill
HAVING:伙计们,你是对的,HAVING应该用于聚合数据。但是GROUP_CONCAT是一个聚合函数。现在我知道了,为什么我用HAVING替换了WHERE:WHERE在分组之前 过滤数据。这意味着,我的GROUP_CONCAT不起作用,我的列category_name包含所有选定行的相同类别名称。
标签: mysql sql group-by group-concat having-clause