简体   繁体   English

完全加入MySQL connectiong 6表

[英]FULL JOIN in MySQL connectiong 6 tables

I have a question about FULL JOIN at MySql. 我在MySql上有一个关于FULL JOIN的问题。 I know that alternative is UNION but I have dificulties to combine them all. 我知道替代方案是UNION,但我很难将它们结合起来。

I guess it would be already enough to get answer on 4 tables as 5th and 6th are same as in first 4. 我想已经足够在4张桌子上得到答案,因为第5和第6张与前4张相同。

Tables: Bill, Service, BS, Item, BI, Buyer 表:比尔,服务,BS,项目,BI,买方

BS connect more Services to Bill and BI connect more Items to Bill . BS将更多服务连接到BillBI将更多项目连接到Bill Buyer is 1:1 relation with Bill . 买方比尔的关系是1:1。

Tables example: 表格示例:

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

So far the closest I got to was that I used following SQL: 到目前为止,我最接近的是我使用了以下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'

Result gives me 2 Services and 1 duplicated Item but I want one Item and one NULL item (as only one item is attached to that bill. 结果给了我2个服务和1个重复的项目,但我想要一个项目和一个NULL项目(因为只有一个项目附加到该账单。

Result that I get (just ids as it's shorter): 我得到的结果(只是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

And desired result in table: 表中所需的结果:

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)

I tried with others as well but I got even more rows than 2 (note that two are expected or if Bill.number=32014 then 4 rows). 我也和其他人一起尝试过但是我得到的行数多于2(注意两个是预期的,或者如果Bill.number = 32014则是4行)。

Thank you! 谢谢!

You are taking the wrong approach. 你采取了错误的做法。

The result of a query to a relational database is a relation - you may treat it as a rectangular matrix with rows and columns. 查询关系数据库的结果是一种关系 - 您可以将其视为具有行和列的矩形矩阵。 Every row represents something (at least it should), every column represents an attribute and every cell represents the thing's attribute's value. 每行代表一些东西 (至少它应该),每列代表一个属性 ,每个单元代表事物的属性值。

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

Now here is what you are trying to produce: 现在,您正在尝试制作:

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

See? 看到? Attempting to return two relations with a single query. 尝试使用单个查询返回两个关系。 Not rectangular anymore, huh? 不再是长方形,是吧? Items and services are independent here, but you are trying to put them into a single row. 项目和服务在这里是独立的,但您试图将它们放在一行中。 Don't go this way, here are three queries for you: 不要这样,这里有三个查询:

-- 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';

Note that item and services queries don't use left joins. 请注意,项目和服务查询不使用左连接。 You would like to return 0 rows if there are no items/services on the bill. 如果账单上没有项目/服务,您希望返回0行。

Then handle the results of them one by one in your application. 然后在您的应用程序中逐个处理它们的结果。

Edit: 编辑:

Sometimes two (or more) entities share some common characteristics, for example in your application you could treat services and items as bill lines. 有时两个(或更多)实体共享一些共同特征,例如在您的应用程序中,您可以将服务和项目视为帐单行。 In this case, this could be valid to retrieve all of them in a single query, but only this way using union: 在这种情况下,这可以在单个查询中检索所有这些,但只有这种方式使用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';

Which will return a result similar to what you originally expected: 这将返回与您最初预期类似的结果:

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

Note that: 注意:

  • each item and service is an individual bill line represented by a record. 每个项目和服务是由记录表示的单个帐单行。 Don't try to artificially "compress" data across rows or columns 不要试图跨行或列人工“压缩”数据
  • it's not the case in your schema, but most often there are also some shared attributes, like line id, quantity ordered or amount paid. 在您的架构中并非如此,但大多数情况下还存在一些共享属性,例如行ID,订购数量或支付金额。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM