【问题标题】:MySQL left join first and second results and return as one rowMySQL左连接第一个和第二个结果并作为一行返回
【发布时间】:2014-05-26 19:16:41
【问题描述】:

我在试图弄清楚如何使用 MySQL 执行此操作时遇到了麻烦。我有一个名为 members 的表和一个名为 contacts 的辅助表。在名为联系人的表中,有一个字段用于存储联系人所针对的成员的 ID。我需要做的是创建一个查询来获取第一个和第二个联系人并将结果作为一行返回。

样本数据:SQLFiddle

members:
=======
member_id | member_name
----------+------------
1         | John Doe
2         | Bob Smith
3         | Suzy Que

contacts:
=========
contact_id | member_id | contact_name
-----------+-----------+-------------
1          | 1         | Jane Doe
2          | 1         | Johnny Doe
3          | 2         | Betty Smith

注意:成员最多可以有 2 个联系人,但不需要联系人。

预期结果:

results:
========
member_id | member_name | contact_1   | contact_2
----------+-------------+-------------+------------
1         | John Doe    | Jane Doe    | Johnny Doe
2         | Bob Smith   | Betty Smith | NULL
3         | Suzy Que    | NULL        | NULL

我的第一个查询:

SELECT
  members.member_id,
  members.member_name,
  c1.contact_name AS contact_1,
  c2.contact_name AS contact_2
FROM
  members
  LEFT JOIN contacts AS c1 ON (members.member_id=c1.member_id)
  LEFT JOIN contacts AS c2 ON (members.member_id=c2.member_id)

返回:

results:
========
member_id | member_name | contact_1   | contact_2
----------+-------------+-------------+------------
1         | John Doe    | Jane Doe    | Jane Doe
1         | John Doe    | Jane Doe    | Johnny Doe
1         | John Doe    | Johnny Doe  | Jane Doe
1         | John Doe    | Johnny Doe  | Johnny Doe
2         | Bob Smith   | Betty Smith | Betty Smith
3         | Suzy Que    | NULL        | NULL

有没有什么方法可以做到这一点,而无需为每个联系人加入执行两个不同的子查询,因为这似乎效率低下。

编辑:

正如@Dag Sondre Hansen 所建议的,这是一种替代解决方案,但我更愿意保留两列。

SELECT
  members.member_id,
  members.member_name,
  group_concat(contacts.contact_name separator ';') as contacts
FROM
  members
  LEFT JOIN contacts ON (members.member_id=contacts.member_id)
GROUP BY
  members.member_id;

【问题讨论】:

  • 如果可以在同一列中返回两个联系人,GROUP_CONCAT 可能会成功。之后需要你拆分字符串。

标签: mysql join left-join


【解决方案1】:
SELECT
  members.member_id,
  members.member_name,
  c1.contact_name AS contact_1,
  c2.contact_name as contact_2
FROM
  members
  LEFT JOIN contacts AS c1 ON (members.member_id=c1.member_id)
  LEFT JOIN contacts as c2 on (members.member_id=c2.member_id AND c1.contact_id <> c2.contact_id)
GROUP BY members.member_id

这对我有用。

注意:这实际上仅适用于每个成员最多 2 个联系人的数据限制。如果这个约束改变了,或者你的程序没有强制执行,那么这里的 SQL 会产生不同的结果。

【讨论】:

    【解决方案2】:

    如果是一种变通方法而不是实际的解决方案,也许这更多,但这里是:

    SELECT   
        members.member_id,   members.member_name,  
        GROUP_CONCAT(c1.contact_name) AS contacts 
    FROM   
        members   
        LEFT JOIN contacts AS c1 ON (members.member_id=c1.member_id) 
    GROUP BY    
        members.member_id;
    

    不过,成员名称会在同一列中弹出。

    【讨论】:

    • AND c1.member_id &lt;=2 几乎没用,并且会阻止更大数据集的功能。
    猜你喜欢
    • 1970-01-01
    • 2018-01-17
    • 2012-10-11
    • 1970-01-01
    • 2019-01-07
    • 1970-01-01
    • 2018-11-23
    • 2014-01-27
    • 1970-01-01
    相关资源
    最近更新 更多