mysql - MySQL 中的 FULL JOIN 连接 6 个表

标签 mysql sql

我对 MySql 的 FULL JOIN 有疑问。我知道替代方案是 UNION,但我很难将它们全部组合起来。

我想在 4 张 table 上得到答案就已经足够了,因为第 5 张和第 6 张 table 与前 4 张 table 相同。

表格:账单、服务、BS、项目、BI、买家

BS 将更多服务连接到BillBI将更多项目连接到比尔买家比尔是1:1的关系。

表格示例:

Bill:
----------------------
id | number | Buyer_id
1  | 12014  |    3
2  | 22014  |    2
3  | 32014  |    5

Services:
----------------------
id | cost
1  |   2
2  |   7
3  |   1
4  |  12

BS:
----------------------
id | Bill_id | Services_id
1  |    1    |     3
2  |    1    |     4
3  |    2    |     2
4  |    3    |     1
5  |    3    |     2
6  |    3    |     3
7  |    3    |     4

Item:
----------------------
id | cost
1  |  34
2  |  77
3  |   2
4  |  15
5  |  13

BI:
----------------------
id | Bill_id | Items_id
1  |    1    |    5
2  |    2    |    3
3  |    3    |    2

Buyer:
----------------------
id | name
1  | John
2  | Mary
3  | Dave
4  | Carl
5  | Jack

到目前为止,我最接近的是使用以下 SQL:

SELECT *
FROM Bill b
LEFT JOIN BI ON BI.Bill_id = b.id
LEFT JOIN BS ON BS.Bill_id = b.id
LEFT JOIN Item i ON i.id = BI.Item_id
LEFT JOIN Services s ON s.id = BS.Services_id
LEFT JOIN Buyer ON Buyer.id = b.Buyer_id
WHERE b.number = '12014'

结果为我提供了 2 项服务和 1 个重复项目,但我想要一项项目和一项 NULL 项目(因为该账单上仅附加了一项项目。

我得到的结果(只是 ids,因为它更短):

b.id | s.id | BS.id | i.id | BI.id | Buyer.id
  1  |   3  |   1   |  1   |   5   |   3
  1  |   4  |   2   |  1   |   5   |   3

表中的期望结果:

b.id | s.id | BS.id | i.id | BI.id | Buyer.id
  1  |   3  |   1   |  1   |   5   |   3
  1  |   4  |   2   | NULL | NULL  |   3 (or NULL, doesn't really matter)

我也尝试过其他人,但我得到的行数甚至超过了 2 行(请注意,预计有 2 行,或者如果 Bill.number=32014 则有 4 行)。

谢谢!

最佳答案

您采取了错误的方法。

对关系数据库的查询结果是一个关系 - 您可以将其视为具有行和列的矩形矩阵。每一行代表某事物(至少应该如此),每一列代表一个属性,每个单元格代表该事物的属性值。

          |  [attr 1]   |  [attr 2]
-----------+---------------+-------------------------
[thing 1] |   value     |   some value
[thing 2] |   value     |   other value
[thing 3] |   a value   |   yeah, a value

现在这是您想要生成的内容:

          |  [attr 1]   |  [attr 2]      |                   |  [other attr 3]
-----------+---------------+------------------+---------------------+-------------------
[thing 1] |   value     |   some value   |  [other thing 1]  |   a value
[thing 2] |   value     |   other value  |                  

看到了吗?尝试使用单个查询返回两个关系。不再是长方形了吧?项目和服务在这里是独立的,但您试图将它们放入一行中。不要走这条路,这里有三个问题要问你:

-- Get bill/buyer details (1 row)
SELECT b.id, Buyer.id
FROM Bill b
LEFT JOIN Buyer ON Buyer.id = b.Buyer_id
WHERE b.number = '12014';

-- Get billed items (1 row per item)
SELECT BI.id, i.id
FROM Bill b
JOIN BI ON BI.Bill_id = b.id
JOIN Item i ON i.id = BI.Item_id
WHERE b.number = '12014';

-- Get billed services (1 row per service)
SELECT BS.id, s.id
FROM Bill b
JOIN BS ON BS.Bill_id = b.id
JOIN Services s ON s.id = BS.Services_id
WHERE b.number = '12014';

请注意,项目和服务查询不使用左联接。如果帐单上没有商品/服务,您希望返回 0 行。

然后在您的应用程序中一一处理它们的结果。

编辑:

有时,两个(或更多)实体具有一些共同特征,例如,在您的应用程序中,您可以将服务和项目视为帐单行。在这种情况下,在单个查询中检索所有这些可能是有效的,但只能使用联合来这种方式:

-- Get bill lines (items and services)
SELECT BI.id AS bill_item_id, i.id AS item_id, NULL as bill_service_id, NULL as service_id
FROM Bill b
JOIN BI ON BI.Bill_id = b.id
JOIN Item i ON i.id = BI.Item_id
WHERE b.number = '12014';
UNION ALL
SELECT NULL AS bill_item_id, NULL AS item_id, BS.id as bill_service_id, s.id as service_id
FROM Bill b
JOIN BS ON BS.Bill_id = b.id
JOIN Services s ON s.id = BS.Services_id
WHERE b.number = '12014';

这将返回与您最初期望的结果类似的结果:

BI.id |  i.id | BS.id | s.id
  5   |   1   | NULL | NULL
NULL  | NULL  |  1   |  3
NULL  | NULL  |  2   |  4

请注意:

  • 每个项目和服务都是由一条记录表示的单独帐单行。不要尝试人为地跨行或列“压缩”数据
  • 您的架构中并非如此,但最常见的是还有一些共享属性,例如行 ID、订购数量或支付金额。

关于mysql - MySQL 中的 FULL JOIN 连接 6 个表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21205775/

相关文章:

mysql - 如何在Access 2007中创建多字段查询?

sql - 如何更新sql server存储过程中的可为空的列

mysql - 使用语句选择整个 IP 范围

mysql - 如何从字段mysql中选择前20个字符后的字符

MySQL INSERT 如果主键值之一不匹配

sql - 与 * 一起使用

php - 允许 php 软件在不超过 3 个计算中运行

sql - postgres 聚合函数调用不能嵌套

mysql - 从消息表中查询对话

mysql - rake 中止! StandardError : An error has occurred, 所有后续迁移均已取消: