在 MySQL 中的同一语句中使用 GROUP_CONCAT、GROUP 和 HAVING

Using GROUP_CONCAT, GROUP, and HAVING in the same statement in MySQL

在应用程序中有 tables projectscategories 和 table,处理它们之间的 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_CONCATGROUP 时,我多了一行。为什么?什么会导致这种行为?

我开始相信您的查询逻辑有误。我建议尝试重写它。最好的方法是退后一步,分解问题,然后再将其重新组合起来。

获取一个类别的所有项目:

SELECT project_id
FROM project_category_info
WHERE category_id = 3;

现在,将其加入 category_info table 以获取这些项目的所有行:

SELECT *
FROM project_category_info
WHERE project_id IN(
   SELECT project_id
   FROM project_category_info
   WHERE category_id = 3);

您可以将其加入项目和类别以获取名称:

SELECT p.id, p.title, c.title
FROM project_category_info pci
JOIN projects p ON p.id = pci.project_
JOIN categories c ON c.id = pci.catgory_id
WHERE pci.project_id IN(
   SELECT project_id
   FROM project_category_info
   WHERE category_id = 3);

现在,您可以将 GROUP_CONAT() 添加到 c.title 列,并按 p.id:

分组
SELECT p.id, p.title, GROUP_CONCAT(c.short_name SEPARATOR '|||') AS category_names
FROM project_category_info pci
JOIN projects p ON p.id = pci.project_
JOIN categories c ON c.id = pci.catgory_id
WHERE pci.project_id IN(
   SELECT project_id
   FROM project_category_info
   WHERE category_id = 3)
GROUP BY p.id;