我在MySql上有一个关于FULL JOIN的问题。我知道替代方案是UNION,但我很难将它们全部合并。
我想已经足够在4张桌子上得到答案,因为第5和第6张与前4张相同。
表格:比尔,服务,BS,项目,BI,买方
BS 将更多服务连接到 Bill , BI 将更多项连接到比尔。 买方与 Bill 的关系是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(注意两个是预期的,或者如果Bill.number = 32014则是4行)。
谢谢!
答案 0 :(得分:2)
你采取了错误的做法。
对关系数据库的查询结果是一种关系 - 您可以将其视为具有行和列的矩形矩阵。每一行代表某事(至少它应该),每列代表一个属性,每个单元代表该事物的属性值。
| [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行。
然后在您的应用程序中逐个处理它们的结果。
修改强> 的
有时两个(或更多)实体共享一些共同特征,例如在您的应用程序中,您可以将服务和项目视为帐单行。在这种情况下,这可以有效地在单个查询中检索所有这些,但只有这种方式使用union:
-- 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
请注意: