讓我們想象兩張桌子:
顧客:
cust_id 1000000001 1000000002 1000000003 1000000004 1000000005 訂單:
cust_id 訂單號 1000000001 20005 1000000003 20006 1000000005 20008 1000000001 20009
以下代碼對我來說非常清楚。它根據cust_id列的相等性比較 2 個表并連接這些表。
SELECT Customers.cust_id, Orders.order_num
FROM Customers
INNER JOIN Orders ON Customers.cust_id = Orders.cust_id;
結果很明顯:
| cust_id | 訂單號 |
|---|---|
| 1000000001 | 20005 |
| 1000000003 | 20006 |
| 1000000005 | 20008 |
| 1000000001 | 20009 |
但是,如果我使用OUTER JOIN具有相同規則的方法:
SELECT Customers.cust_id, Orders.order_num
FROM Customers
FULL OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id;
我會得到:
| cust_id | 訂單號 |
|---|---|
| 1000000001 | 20005 |
| 1000000001 | 20009 |
| 1000000002 | 無效的 |
| 1000000003 | 20006 |
| 1000000004 | 無效的 |
| 1000000005 | 20008 |
這個結果對我來說很清楚,我知道做什么FULL OUTER JOIN,但我發現這個方法需要相等規則的事實非常模糊,因為代碼從第一個表中回傳了一些不在第二個表中的行。那么,如果只是忽略它,為什么我們需要這條規則呢?我們可以使用不同的條件,例如 != 來避免混淆嗎?
uj5u.com熱心網友回復:
您將交叉連接與內部/外部(左、右、全)連接混淆了。交叉連接將在沒有條件的情況下將每一行與其他每一行匹配。內/外連接匹配滿足 ON 子句中條件的那些。內連接和外連接之間的主要區別在于如何處理不匹配。不匹配概念不適用于交叉連接。
嘗試運行這些查詢作為示例。請注意最后幾個使用完全外連接的查詢。1=1 的 ON 子句模擬交叉連接。1=0 的 ON 子句從每個表中回傳一條記錄。
順便說一句,我在 1=1 的 ON 子句中添加了一個 ORDER BY,因為該順序不是交叉連接的順序。(希望它易于比較。)即使沒有 ORDER BY 子句,對于這個非常小的示例,使用交叉連接的這個技巧的成本大約是 100 倍。
set nocount on
print 'Inner join:'
select *
from (
values (1,'A'),(2,'B'),(3,'C'),(25,'Y')
) t1 (id, val)
inner join (
values (1, 'A'),(2,'B'),(3,'C'),(26,'Z')
) t2 (id, val)
ON t1.id = t2.id
print 'Left outer join:'
select *
from (
values (1,'A'),(2,'B'),(3,'C'),(25,'Y')
) t1 (id, val)
left outer join (
values (1, 'A'),(2,'B'),(3,'C'),(26,'Z')
) t2 (id, val)
ON t1.id = t2.id
print 'Right outer join:'
select *
from (
values (1,'A'),(2,'B'),(3,'C'),(25,'Y')
) t1 (id, val)
right outer join (
values (1, 'A'),(2,'B'),(3,'C'),(26,'Z')
) t2 (id, val)
ON t1.id = t2.id
print 'Full outer join:'
select *
from (
values (1,'A'),(2,'B'),(3,'C'),(25,'Y')
) t1 (id, val)
full outer join (
values (1, 'A'),(2,'B'),(3,'C'),(26,'Z')
) t2 (id, val)
ON t1.id = t2.id
print 'Cross join:'
select *
from (
values (1,'A'),(2,'B'),(3,'C'),(25,'Y')
) t1 (id, val)
cross join (
values (1, 'A'),(2,'B'),(3,'C'),(26,'Z')
) t2 (id, val)
print 'Full outer join with everything matching anything - a fake cross join:'
select *
from (
values (1,'A'),(2,'B'),(3,'C'),(25,'Y')
) t1 (id, val)
full outer join (
values (1, 'A'),(2,'B'),(3,'C'),(26,'Z')
) t2 (id, val)
ON 1 = 1
ORDER BY t1.id, t2.id
print 'Full outer join with no matches ever:'
select *
from (
values (1,'A'),(2,'B'),(3,'C'),(25,'Y')
) t1 (id, val)
full outer join (
values (1, 'A'),(2,'B'),(3,'C'),(26,'Z')
) t2 (id, val)
ON 1 = 0
Inner join:
id val id val
----------- ---- ----------- ----
1 A 1 A
2 B 2 B
3 C 3 C
Left outer join:
id val id val
----------- ---- ----------- ----
1 A 1 A
2 B 2 B
3 C 3 C
25 Y NULL NULL
Right outer join:
id val id val
----------- ---- ----------- ----
1 A 1 A
2 B 2 B
3 C 3 C
NULL NULL 26 Z
Full outer join:
id val id val
----------- ---- ----------- ----
1 A 1 A
2 B 2 B
3 C 3 C
NULL NULL 26 Z
25 Y NULL NULL
Cross join:
id val id val
----------- ---- ----------- ----
1 A 1 A
1 A 2 B
1 A 3 C
1 A 26 Z
2 B 1 A
2 B 2 B
2 B 3 C
2 B 26 Z
3 C 1 A
3 C 2 B
3 C 3 C
3 C 26 Z
25 Y 1 A
25 Y 2 B
25 Y 3 C
25 Y 26 Z
Full outer join with everything matching anything - a fake cross join:
id val id val
----------- ---- ----------- ----
1 A 1 A
1 A 2 B
1 A 3 C
1 A 26 Z
2 B 1 A
2 B 2 B
2 B 3 C
2 B 26 Z
3 C 1 A
3 C 2 B
3 C 3 C
3 C 26 Z
25 Y 1 A
25 Y 2 B
25 Y 3 C
25 Y 26 Z
Full outer join with no matches ever:
id val id val
----------- ---- ----------- ----
1 A NULL NULL
2 B NULL NULL
3 C NULL NULL
25 Y NULL NULL
NULL NULL 1 A
NULL NULL 2 B
NULL NULL 3 C
NULL NULL 26 Z
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/485856.html
上一篇:獲取列的總和而不洗掉一些記錄
