在上篇文章中,我們的測試用表,沒一行都是唯一的,也就是沒有重複值,如果有重複值,結論會不會變呢?
2. 2 張表,值不唯的情況。
2.1 創建測試用表。
DROP TABLE IF EXISTS table1; DROP TABLE IF EXISTS table2; CREATE TABLE table1 ( column_1 NUMERIC ); INSERT INTO table1 VALUES (123); INSERT INTO table1 VALUES (123); INSERT INTO table1 VALUES (12); INSERT INTO table1 VALUES (12); INSERT INTO table1 VALUES (111); INSERT INTO table1 VALUES (111); CREATE TABLE table2 ( column_2 NUMERIC ); INSERT INTO table2 VALUES (123); INSERT INTO table2 VALUES (123); INSERT INTO table2 VALUES (12); INSERT INTO table2 VALUES (12); INSERT INTO table2 VALUES (23); INSERT INTO table2 VALUES (23);
2.2. 查看錶裏的內容
查詢 2-2-1: 查詢表 1 內容。
SELECT * FROM table1 t1;
輸出 2-2-1:
123
123
12
12
111
111
查詢 2-2-2: 查詢表 2 內容。
SELECT * FROM table2 t2;
輸出 2-2-2:
123
123
12
12
23
23
查詢 2-2-3: 全連接
SELECT * FROM table1 t1 FULL OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 ORDER BY column_1, column_2;
輸出 2-2-3:
12 12
12 12
12 12
12 12
111
111
123 123
123 123
123 123
123 123
23
23
查詢 2-2-4: 使用 UNION 合併左連接和右連接
SELECT * FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 UNION SELECT * FROM table1 t1 RIGHT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 ORDER BY column_1, column_2;
輸出:2-2-4:
12 12
111
123 123
23
解釋 2-2-4: 輸出 2-2-4 只有 4 行,而輸出 2-2-3 有 12 行。因爲 UNION 默認會刪除重複的行,UNION ALL 則不會刪除重複行。下面試試 UNION ALL:
查詢 2-2-5: 使用 UNION ALL 合併左連接和右連接。
SELECT * FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 UNION ALL SELECT * FROM table1 t1 RIGHT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 ORDER BY column_1, column_2;
輸出 2-2-5:
12 12
12 12
12 12
12 12
12 12
12 12
12 12
12 12
111
111
123 123
123 123
123 123
123 123
123 123
123 123
123 123
123 123
23
23
解釋 2-2-5: 輸出 2-2-5 有 20 行,我們目標是想要獲得 2-2-3, 只有 12 行。怎樣才能使用左連接和右連接來獲取這 10 行呢?目前來看,使用 UNION 或者 UNION ALL 拼接左連接和右連接都不行。
先來總結一下每種查詢的行數,看看能不能有什麼規律:
a. table1: 6 行。
b. table2: 6 行。
c. 內連接:8 行。
d. 左連接:10 行。
e. 右連接:10 行。
f. 全連接:12 行。
g. UNION 左連接和右連接:4 行。
h. UNION ALL 左連接和有連接:20 行。
猜想:h(20 行) - c(8 行) = f(12 行)。
下面進行驗證。找了一下,UNION ALL 相當於查詢結果相加,EXCETP 相當於相減。下面試一下 EXCETP:
查詢 2-2-6: 使用 EXCETP 來刪除一些行:
SELECT * FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 UNION ALL SELECT * FROM table1 t1 RIGHT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 EXCEPT SELECT * FROM table1 t1 INNER JOIN table2 t2 ON t1.column_1 = t2.column_2 ORDER BY column_1, column_2;
輸出 2-2-6:
111
23
解釋 2-2-6: 只有兩行,沒有獲得我們想要的 12 行。分析原因:h(20 行) - c(8 行) = f(12 行) 這邊的 h、c、f 都有重複的行,我們在使用 EXCETP 刪除一些行的時候,比如 h 中有 line 1, line 2, 這兩行是一樣的,c 中有一行 line 3, 我們想要的結果是隻刪除 line 1, 但是 EXCETP 分不清 line 1 和 line 2,所以把 line 1 和 line 2 全刪了。應該想辦法 刪除 line 1 保留 line 2.
查詢 2-2-7: 使用 EXCETP 來刪除左連接中的行,然後在與右連接 UNION ALL:
SELECT * FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 EXCEPT SELECT * FROM table1 t1 INNER JOIN table2 t2 ON t1.column_1 = t2.column_2 UNION ALL SELECT * FROM table1 t1 RIGHT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 ORDER BY column_1, column_2;
輸出 2-2-7:
12 12
12 12
12 12
12 12
111
123 123
123 123
123 123
123 123
23
23
解釋 2-2-7: 只有 11 行,並沒有我們想要的 12 行。對比輸出 2-2-3 和 2-2-7,我們發現少了這一行:
111
下面來分析這一行是怎麼少了的。
查詢 2-2-8: 左連接 EXCEPT 內連接。
SELECT * FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 EXCEPT SELECT * FROM table1 t1 INNER JOIN table2 t2 ON t1.column_1 = t2.column_2;
輸出 2-2-8:
111
解釋:左連接 10 行,內連接 8 行,左連接 EXCEPT 內連接只有 1 行。我們想要的是 2 行,不過這兩行內容是一樣的。難道 EXCEPT 有自動去重功能?
查詢 2-2-9: 測試 EXCEPT 是否自帶去重複功能。
SELECT * FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 EXCEPT SELECT * FROM table1 t1 INNER JOIN table2 t2 ON t1.column_1 = -1;
輸出:
123 123
12 12
111
解釋 2-2-9: 果然,EXCPET 是有自動去重複功能的。左連接有 10 行,只有 3 行是互不相同的,使用了 EXCPET 之後,只顯示了這 3 行。這裏 EXCPET 後面的子查詢的結果是空集,因爲 table1 中沒有 column_1 = -1 的行。UNION 後面加上 ALL 之後,去重功能就沒有了,那麼 EXCEPT 是不是也是這樣呢?下面試一下:
查詢 2-2-10: 左連接 EXCEPT ALL 內連接。
SELECT * FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 EXCEPT ALL SELECT * FROM table1 t1 INNER JOIN table2 t2 ON t1.column_1 = t2.column_2 ORDER BY column_1, column_2;
輸出 2-2-10:
111
111
解釋 2-2-10: 結果有 10 行,正是我們想要的 2 行。下面試一下左連接 EXCEPT ALL 內連接 UNION ALL 右連接。
查詢 2-2-11: 左連接 EXCEPT ALL 內連接 UNION ALL 右連接。
SELECT * FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 EXCEPT ALL SELECT * FROM table1 t1 INNER JOIN table2 t2 ON t1.column_1 = t2.column_2 UNION ALL SELECT * FROM table1 t1 RIGHT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 ORDER BY column_1, column_2;
輸出 2-2-11:
12 12
12 12
12 12
12 12
111
111
123 123
123 123
123 123
123 123
23
23
解釋 2-2-11: 結果有 12 行,與全連接的結果一樣,正是我們想要的。
總結:
在 2 張表的情況下,全連接等效於:左連接 EXCEPT ALL 內連接 UNION ALL 右連接。