首页 > 解决方案 > 加入 MySQL 关系只输出一行

问题描述

我有两个都与用户相关的表。

有问题的三个表是:用户、经销商、领子。

这里的问题是一个用户可以有很多项圈,我的联接语句只输出一个项圈,即使有多个关联。

但是,我知道它正在查找与 user_id 关联的多个项圈,因为如果我改为添加GROUP_CONCAT(collars.collar_id)到我的 sql 语句中,它将显示用户拥有的两个项圈。

它输出一个项圈,因为它返回到的数组具有每个项圈输出都覆盖的键,因为不能有重复的数组键。

这是我的 SELECT 语句:

SELECT u.*
     , d.*
     , c.*
  FROM users u
  JOIN dealers d
    ON d.id = u.dealer_id_foreign
  JOIN user_collars uc
    ON uc.user_id = u.user_id
  JOIN collars c
    ON c.collar_id = uc.collar_id
 WHERE u.user_id = :id

我的问题是,我可以使用一条 SQL 语句来返回我想要的与该用户相关的所有信息吗?也许是一个多维数组,所以可以返回所有项圈?

注意:我正在使用 PHP PDO 来执行此操作。这就是 select 语句中的 ":id" 变量。

编辑:我将提供一个更完整的表结构示例以及我希望通过 SELECT 语句实现的数组输出。

用户表:

+---------+-------------------+
| user_id | dealer_id_foreign |
+---------+-------------------+
|    1811 |                55 |
|    1812 |                67 |
+---------+-------------------+

经销商表

+----+--------------------+
| id |    dealer name     |
+----+--------------------+
| 55 | dealer guy         |
| 56 | another dealer guy |
+----+--------------------+

衣领表

+-----------+---------------------+
| collar_id |        name         |
+-----------+---------------------+
|        26 | some collar name    |
|        27 | another collar name |
+-----------+---------------------+

User_Collars 表(关系表)

+-----------+---------+
| collar_id | user_id |
+-----------+---------+
|        26 |    1811 |
|        27 |    1811 |
+-----------+---------+

如您所见,ID 为“1811”的用户拥有两个项圈。当我通过 id 查询用户时,在本例中为 1811,我希望通过查询输出所有关系信息,即用户连接到的经销商和他们拥有的所有项圈。

我不会在示例数组中包含所有内容,但这应该是示例

Array (

[user_id] => 1811
[user_name] => 'whatever'
[dealer_name] 'the dealer name',
[collars] => [
  [some_key_1] => [
    [collar_id] => 26
  ],

  [some_key_2] => [
    [collar_id] => 27
  ]
]
)

现在我意识到我要求 MySQL 提供格式,我知道这是不合理的,但我本质上想要的是能够获取所有项的单个记录输出。

标签: mysql

解决方案


您的查询没有任何问题,它正确返回了两行数据,如您在此dbfiddle中所见:

user_id     dealer_id_foreign   id  dealer name     collar_id   name
1811        5              5    55  dealer guy      26          some collar name
1811        55                  55  dealer guy      27          another collar name

如果要在一行中获取所有信息,则需要按以下方式对衣领值进行分组user_id

SELECT u.user_id
     , d.id AS dealer_id
     , d.`dealer name`
     , GROUP_CONCAT(c.collar_id) AS collar_ids
     , GROUP_CONCAT(c.name) AS collar_names
  FROM users u
  JOIN dealers d
    ON d.id = u.dealer_id_foreign
  JOIN user_collars uc
    ON uc.user_id = u.user_id
  JOIN collars c
    ON c.collar_id = uc.collar_id
 WHERE u.user_id = 1811
 GROUP BY u.user_id, d.id

这将在结果中为您提供以逗号分隔的衣领 ID 和名称值列表(针对每个用户/经销商组合):

user_id     dealer_id   dealer name     collar_ids  collar_names
1811        55          dealer guy      26,27       some collar name,another collar name

dbfiddle 演示

然后,在您的应用程序框架中,您可以组合衣领 id 和名称值,例如在 PHP 中,您可能会执行以下操作:

$collars = array_combine(explode(',', $row['collar_ids']), explode(',', $row['collar_names']));

这会给你一个像这样的输出:

Array ( 
    [26] => some collar name
    [27] => another collar name 
)

或者,如果您只想要领子 ID

$collars = explode(',', $row['collar_ids']);

这会给你一个像这样的输出:

Array ( 
    [0] => 26
    [1] => 27
)

推荐阅读