使用 GROUP_CONCAT 进行 LEFT JOIN 的奇怪结果

Posted

技术标签:

【中文标题】使用 GROUP_CONCAT 进行 LEFT JOIN 的奇怪结果【英文标题】:Strange Results on LEFT JOIN with GROUP_CONCAT 【发布时间】:2016-05-11 10:31:10 【问题描述】:

我想为我的每个用户获取一些属性。每个用户可以拥有多个设备并注册到多个项目,当然反之亦然(因此是多对多的关系)。

为此,我有三个相关表:将用户链接到设备的表、将用户链接到项目的表和设备表。我暂时将 users 表排除在外,以简化查询(因此我只是为从单独查询中获得的每个用户迭代查询)。

我想要的是能够为每个用户以及每个用户/设备对显示一个设备列表——一个项目列表。这适用于以下查询:

SELECT `user_devices`.*, `devices`.`id`, `devices`.`type`, `devices`.`number`, `user_projects`.`project_id` AS `projects`
        FROM `user_devices`
        LEFT JOIN `devices` ON `user_devices`.`device_id` = `devices`.`id`
        LEFT JOIN `user_projects` ON `user_devices`.`user_id` = `user_projects`.`user_id`
            AND `user_devices`.`device_id` = `user_projects`.`device_id`
        WHERE `user_devices`.`user_id` = $user_id;

但是,即使使用相同的用户/设备组合,它也会为每个项目包含一行,这需要后处理(我使用的是 php),这很烦人。因此我决定像这样使用GROUP_CONCAT

SELECT `user_devices`.*, `devices`.`id`, `devices`.`type`, `devices`.`number`, GROUP_CONCAT(`user_projects`.`project_id`) AS `projects`
        FROM `user_devices`
        LEFT JOIN `devices` ON `user_devices`.`device_id` = `devices`.`id`
        LEFT JOIN `user_projects` ON `user_devices`.`user_id` = `user_projects`.`user_id`
            AND `user_devices`.`device_id` = `user_projects`.`device_id`
        WHERE `user_devices`.`user_id` = $user_id;

然而,无论如何,现在它只返回一行,包括 NULL 行(似乎忽略了应该只获取包含第一个表中的值的行的 LEFT JOIN)。它确实包含正确的项目列表,但即使该用户有多个设备,每个用户也只列出一个设备。

我认为这可能是我对 LEFT JOIN 如何与组函数一起工作的误解,但我无法弄清楚。

【问题讨论】:

【参考方案1】:

原来这确实是我对GROUP_CONCAT的误解。事实证明,如果没有相应的GROUP BY,它就无法工作。

由于在这种情况下逻辑上需要按设备显示项目,因此可以按devices.number进行分组:

GROUP BY `devices`.`number`

【讨论】:

以上是关于使用 GROUP_CONCAT 进行 LEFT JOIN 的奇怪结果的主要内容,如果未能解决你的问题,请参考以下文章

GROUP_CONCAT 与 LEFT JOIN 条件?

GROUP_CONCAT 与两个表的 LEFT OUTER JOIN

带有 LEFT JOIN 和 IF 语句的有限 GROUP_CONCAT

GROUP_CONCAT 和 LEFT_JOIN 问题 - 并非所有行都返回

来自 GROUP_BY 的两个 LEFT JOIN 的 GROUP_CONCAT 的奇怪重复行为

当 LEFT JOINing 两个不同的表时,GROUP_CONCAT 接触了太多的重复值