【问题标题】:Join twice table with two foreign keys用两个外键加入两次表
【发布时间】:2019-08-14 08:01:12
【问题描述】:

我想提取有关存储在我的数据库中的人员和公司的信息。我有 2 个表(客户和联系人)指向包含 2 个外键(addressClientID 和 addressContactID)的唯一地址表。 客户可以有多个地址,联系人通常是一个,它可以是自定义地址(addressContactID 将指向联系人 ID,否则为 NULL)或为其工作的客户的地址。 查询应提取联系人姓名、联系人工作的公司名称和城市。后者必须是公司所在的城市(如果 addressContactID 为 NULL)或联系人所在的城市(如果 addressContactID 指向一个联系人 ID)。

我尝试了多种类型的连接,但均未成功。 DBMS 是 MySql 5.2

mysql> select * from Clients;
+----+---------+-------------+--------+
| id | name    | taxCode     | optOut |
+----+---------+-------------+--------+
|  1 | Client1 | 51824753556 |      0 |
|  2 | Client2 | 51824543536 |      0 |
+----+---------+-------------+--------+
2 rows in set (0.01 sec)

mysql> select * from Contacts;
+----+--------------+---------------+------------------------+------------------+------------------+--------------+-------+------------------+
| id | name         | preferredName | email                  | mobile           | phone            | jobTitle     | notes | contactsClientId |
+----+--------------+---------------+------------------------+------------------+------------------+--------------+-------+------------------+
|  1 | Contact 1    | NULL          | contact1@gmail.com     | +61 421 111111   | +61 421 22222222 | Title1       | NULL  |                1 |
|  2 | Contact 2    | NULL          | contact2@gmail.com     | +61 421 15345431 | +61 421 263462   | Title2       | NULL  |                2 |
|  4 | Contact 3    | NULL          | contact3@fdsfsd.com    | NULL             | NULL             | Title3       | NULL  |                1 |
+----+--------------+---------------+------------------------+------------------+------------------+--------------+-------+------------------+
3 rows in set (0.00 sec)

mysql> select * from Address;
+----+-------------+---------+----------+-------+-----------+-----------------+------------------+---------------------+
| id | address     | city    | postcode | state | country   | addressClientId | addressContactId | addressEngagementId |
+----+-------------+---------+----------+-------+-----------+-----------------+------------------+---------------------+
|  1 | Address n.1 | Sydney  | 2000     | NSW   | Australia |               1 |             NULL |                NULL |
|  2 | Address n.2 | Adelaide| 2010     | NSW   | Australia |               2 |             NULL |                NULL |
| 19 | Address n.3 | Perth   | 2050     | NSW   | Australia |               1 |                4 |                NULL |
+----+-------------+---------+----------+-------+-----------+-----------------+------------------+---------------------+
3 rows in set (0.01 sec)

预期的结果是这样的

ContactName, CompanyName, City

Contact 1, Client1, Sydney
Contact 2, Client1, Adelaide
Contact 3, Client2, Perth

【问题讨论】:

  • 示例数据(作为文本)会很有用。
  • 刚刚添加了一些!
  • 是“(公司所在城市)”预期输出的一部分,或者只是对问题的有用评论。如果是后者,你怎么知道地址属于什么(公司或联系人)?
  • 不,这不是预期的输出,我只是为了清楚起见而添加了它(我再次更改了帖子以反映表格上的数据)
  • 我想CompanyName 应该是ClientName,不应该是?

标签: mysql sql join


【解决方案1】:

这是我想出的:

SELECT co.name, cl.name, IF(a1.id IS NULL, a2.city, a1.city) AS city
FROM Contacts co
JOIN Clients cl
     ON co.contactsClientId = cl.id
LEFT JOIN Address a1
     ON co.id = a1.addressContactId
LEFT JOIN Address a2
     ON cl.id = a2.addressClientId
     AND a1.id IS NULL
     AND a2.addressContactId IS NULL
ORDER BY co.name

但是请注意,您的 Contact 1 正在为有两个地址的 Client1 工作。所以我添加了AND a2.addressContactId IS NULL 行,在这种情况下只选择一个没有分配addressContactId 的地址,但是根据你的真实数据,你可能仍然会得到重复(如果你有一个联系人为一家有两个地址但没有@987654326 的公司工作@,例如)

【讨论】:

    【解决方案2】:

    您可以在这三个表中使用left join,如下表顺序:

    select cn.name as ContactName, cl.name as ClientName, ad.city
      from Contacts cn
      left join Clients cl on cl.id = cn.contactsClientId 
      left join Address ad on ad.addressClientId = cl.id and ad.addressContactId = cn.id
     order by ContactName;
    

    考虑 Demo,如果你有 Demo 中的数据,那么你就能得到想要的结果。

    【讨论】:

    • 这会返回重复的结果:2x Contact 1(每个城市一个)和 2x Contact 2(与之前相同)
    • @Claudio 是的,我也意识到了,但它与数据有关
    猜你喜欢
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 2011-10-23
    • 2018-06-21
    • 1970-01-01
    • 2016-08-25
    • 2014-06-13
    相关资源
    最近更新 更多