在前两篇文章中,我们都是使用的 2 张表,如果是 3 张表,结论会不会变呢?我们来试一下。
3. 3 张表,值不唯一的情况。
3.1 创建测试用表。
DROP TABLE IF EXISTS table1; 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); DROP TABLE IF EXISTS table2; 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); DROP TABLE IF EXISTS table3; CREATE TABLE table3 ( column_3 NUMERIC(30) ); INSERT INTO table3 VALUES (123); INSERT INTO table3 VALUES (123); INSERT INTO table3 VALUES (333); INSERT INTO table3 VALUES (333); INSERT INTO table3 VALUES (23); INSERT INTO table3 VALUES (23);
查询 3-2-1: 全连接
SELECT * FROM table1 t1 FULL OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 FULL OUTER JOIN table3 t3 ON t1.column_1 = t3.column_3 ORDER BY column_1, column_2, column_3;
输出 3-2-1:
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 123 123
123 123 123
123 123 123
23
23
23
23
333
333
尝试了多种办法,直接给出最后的可行办法:
查询 3-2-2: 使用左连接、右连接、内连接模拟全连接。
SELECT * FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 LEFT OUTER JOIN table3 t3 ON t1.column_1 = t3.column_3 UNION ALL SELECT * FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 RIGHT OUTER JOIN table3 t3 ON t1.column_1 = t3.column_3 UNION ALL SELECT * FROM table1 t1 RIGHT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 LEFT OUTER JOIN table3 t3 ON t1.column_1 = t3.column_3 UNION ALL SELECT * FROM table1 t1 RIGHT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 RIGHT OUTER JOIN table3 t3 ON t1.column_1 = t3.column_3 EXCEPT ALL SELECT * FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 INNER JOIN table3 t3 ON t1.column_1 = t3.column_3 EXCEPT ALL SELECT * FROM table1 t1 RIGHT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 INNER JOIN table3 t3 ON t1.column_1 = t3.column_3 EXCEPT ALL SELECT * FROM table1 t1 INNER JOIN table2 t2 ON t1.column_1 = t2.column_2 LEFT OUTER JOIN table3 t3 ON t1.column_1 = t3.column_3 EXCEPT ALL SELECT * FROM table1 t1 INNER JOIN table2 t2 ON t1.column_1 = t2.column_2 RIGHT OUTER JOIN table3 t3 ON t1.column_1 = t3.column_3 UNION ALL SELECT * FROM table1 t1 INNER JOIN table2 t2 ON t1.column_1 = t2.column_2 INNER JOIN table3 t3 ON t1.column_1 = t3.column_3 ORDER BY column_1, column_2, column_3;
看上去很复杂。如果有更多的表,那就更复杂了。比如:
查询 3-2-3: 复杂的全连接:
SELECT * FROM table1 t1 FULL OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 INNER OUTER JOIN table3 t3 ON t1.column_1 = t3.column_3 FULL OUTER JOIN table3 t3 ON t2.column_1 = t3.column_4 LEFT JOIN table3 t3 ON t2.column_1 = t3.column_4 ORDER BY column_1, column_2, column_3, column_4;
还有一个办法是使用 view:
查询 3-2-4:
DROP VIEW IF EXISTS join_1_2; CREATE VIEW join_1_2 AS 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; SELECT * FROM join_1_2 t1_2 LEFT OUTER JOIN table3 t3 ON t1_2.column_1 = t3.column_3 EXCEPT ALL SELECT * FROM join_1_2 t1_2 INNER JOIN table3 t3 ON t1_2.column_1 = t3.column_3 UNION ALL SELECT * FROM join_1_2 t1_2 RIGHT OUTER JOIN table3 t3 ON t1_2.column_1 = t3.column_3 ORDER BY column_1, column_2, column_3;
输出 3-2-4:
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 123 123
123 123 123
123 123 123
23
23
23
23
333
333
解释 3-2-4: 可以看出 3-2-1 的输出和 3-2-4 的输出是一致的。
经过测试,view table 的方法在 4 张表的情况下也是正确的,就不一一做实验了,下面直接给出所有SQL:
DROP TABLE IF EXISTS table1 CASCADE; CREATE TABLE table1 ( column_1 NUMERIC ); INSERT INTO table1 VALUES (1); INSERT INTO table1 VALUES (1); INSERT INTO table1 VALUES (12); INSERT INTO table1 VALUES (12); INSERT INTO table1 VALUES (13); INSERT INTO table1 VALUES (13); INSERT INTO table1 VALUES (14); INSERT INTO table1 VALUES (14); INSERT INTO table1 VALUES (123); INSERT INTO table1 VALUES (123); INSERT INTO table1 VALUES (124); INSERT INTO table1 VALUES (124); INSERT INTO table1 VALUES (134); INSERT INTO table1 VALUES (134); INSERT INTO table1 VALUES (1234); INSERT INTO table1 VALUES (1234); DROP TABLE IF EXISTS table2 CASCADE; CREATE TABLE table2 ( column_2 NUMERIC ); INSERT INTO table2 VALUES (2); INSERT INTO table2 VALUES (2); INSERT INTO table2 VALUES (12); INSERT INTO table2 VALUES (12); INSERT INTO table2 VALUES (23); INSERT INTO table2 VALUES (23); INSERT INTO table2 VALUES (24); INSERT INTO table2 VALUES (24); INSERT INTO table2 VALUES (123); INSERT INTO table2 VALUES (123); INSERT INTO table2 VALUES (124); INSERT INTO table2 VALUES (124); INSERT INTO table2 VALUES (234); INSERT INTO table2 VALUES (234); INSERT INTO table2 VALUES (1234); INSERT INTO table2 VALUES (1234); DROP TABLE IF EXISTS table3 CASCADE; CREATE TABLE table3 ( column_3 NUMERIC ); INSERT INTO table3 VALUES (3); INSERT INTO table3 VALUES (3); INSERT INTO table3 VALUES (13); INSERT INTO table3 VALUES (13); INSERT INTO table3 VALUES (23); INSERT INTO table3 VALUES (23); INSERT INTO table3 VALUES (34); INSERT INTO table3 VALUES (34); INSERT INTO table3 VALUES (123); INSERT INTO table3 VALUES (123); INSERT INTO table3 VALUES (134); INSERT INTO table3 VALUES (134); INSERT INTO table3 VALUES (234); INSERT INTO table3 VALUES (234); INSERT INTO table3 VALUES (1234); INSERT INTO table3 VALUES (1234); DROP TABLE IF EXISTS table4 CASCADE; CREATE TABLE table4 ( column_4 NUMERIC ); INSERT INTO table4 VALUES (4); INSERT INTO table4 VALUES (4); INSERT INTO table4 VALUES (14); INSERT INTO table4 VALUES (14); INSERT INTO table4 VALUES (24); INSERT INTO table4 VALUES (24); INSERT INTO table4 VALUES (34); INSERT INTO table4 VALUES (34); INSERT INTO table4 VALUES (124); INSERT INTO table4 VALUES (124); INSERT INTO table4 VALUES (134); INSERT INTO table4 VALUES (134); INSERT INTO table4 VALUES (234); INSERT INTO table4 VALUES (234); INSERT INTO table4 VALUES (1234); INSERT INTO table4 VALUES (1234); SELECT * FROM table1 t1; SELECT * FROM table2 t2; SELECT * FROM table2 t3; SELECT * FROM table2 t4; SELECT * FROM table1 t1 FULL OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 FULL OUTER JOIN table3 t3 ON t2.column_2 = t3.column_3 FULL OUTER JOIN table4 t4 ON t3.column_3 = t4.column_4 ORDER BY column_1, column_2, column_3, column_4; DROP VIEW IF EXISTS join_1_2 CASCADE; CREATE VIEW join_1_2 AS 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; DROP VIEW IF EXISTS join_1_2_3 CASCADE; CREATE VIEW join_1_2_3 AS SELECT * FROM join_1_2 t1 LEFT OUTER JOIN table3 t3 ON t1.column_2 = t3.column_3 EXCEPT ALL SELECT * FROM join_1_2 t1 INNER JOIN table3 t3 ON t1.column_2 = t3.column_3 UNION ALL SELECT * FROM join_1_2 t1 RIGHT OUTER JOIN table3 t3 ON t1.column_2 = t3.column_3; DROP VIEW IF EXISTS join_1_2_3_4 CASCADE; CREATE VIEW join_1_2_3_4 AS SELECT * FROM join_1_2_3 t1 LEFT OUTER JOIN table4 t4 ON t1.column_3 = t4.column_4 EXCEPT ALL SELECT * FROM join_1_2_3 t1 INNER JOIN table4 t4 ON t1.column_3 = t4.column_4 UNION ALL SELECT * FROM join_1_2_3 t1 RIGHT OUTER JOIN table4 t4 ON t1.column_3 = t4.column_4; SELECT * FROM join_1_2_3_4 ORDER BY column_1 NULLS FIRST, column_2 NULLS FIRST, column_3 NULLS FIRST, column_4 NULLS FIRST;
MySQL 不支持 EXCEPT,可以使用 WHERE 达到相同的效果,SQL 如下:
DROP TABLE IF EXISTS table1 CASCADE; CREATE TABLE table1 ( column_1 NUMERIC ); INSERT INTO table1 VALUES (1); INSERT INTO table1 VALUES (1); INSERT INTO table1 VALUES (12); INSERT INTO table1 VALUES (12); INSERT INTO table1 VALUES (13); INSERT INTO table1 VALUES (13); INSERT INTO table1 VALUES (14); INSERT INTO table1 VALUES (14); INSERT INTO table1 VALUES (123); INSERT INTO table1 VALUES (123); INSERT INTO table1 VALUES (124); INSERT INTO table1 VALUES (124); INSERT INTO table1 VALUES (134); INSERT INTO table1 VALUES (134); INSERT INTO table1 VALUES (1234); INSERT INTO table1 VALUES (1234); DROP TABLE IF EXISTS table2 CASCADE; CREATE TABLE table2 ( column_2 NUMERIC ); INSERT INTO table2 VALUES (2); INSERT INTO table2 VALUES (2); INSERT INTO table2 VALUES (12); INSERT INTO table2 VALUES (12); INSERT INTO table2 VALUES (23); INSERT INTO table2 VALUES (23); INSERT INTO table2 VALUES (24); INSERT INTO table2 VALUES (24); INSERT INTO table2 VALUES (123); INSERT INTO table2 VALUES (123); INSERT INTO table2 VALUES (124); INSERT INTO table2 VALUES (124); INSERT INTO table2 VALUES (234); INSERT INTO table2 VALUES (234); INSERT INTO table2 VALUES (1234); INSERT INTO table2 VALUES (1234); DROP TABLE IF EXISTS table3 CASCADE; CREATE TABLE table3 ( column_3 NUMERIC ); INSERT INTO table3 VALUES (3); INSERT INTO table3 VALUES (3); INSERT INTO table3 VALUES (13); INSERT INTO table3 VALUES (13); INSERT INTO table3 VALUES (23); INSERT INTO table3 VALUES (23); INSERT INTO table3 VALUES (34); INSERT INTO table3 VALUES (34); INSERT INTO table3 VALUES (123); INSERT INTO table3 VALUES (123); INSERT INTO table3 VALUES (134); INSERT INTO table3 VALUES (134); INSERT INTO table3 VALUES (234); INSERT INTO table3 VALUES (234); INSERT INTO table3 VALUES (1234); INSERT INTO table3 VALUES (1234); DROP TABLE IF EXISTS table4 CASCADE; CREATE TABLE table4 ( column_4 NUMERIC ); INSERT INTO table4 VALUES (4); INSERT INTO table4 VALUES (4); INSERT INTO table4 VALUES (14); INSERT INTO table4 VALUES (14); INSERT INTO table4 VALUES (24); INSERT INTO table4 VALUES (24); INSERT INTO table4 VALUES (34); INSERT INTO table4 VALUES (34); INSERT INTO table4 VALUES (124); INSERT INTO table4 VALUES (124); INSERT INTO table4 VALUES (134); INSERT INTO table4 VALUES (134); INSERT INTO table4 VALUES (234); INSERT INTO table4 VALUES (234); INSERT INTO table4 VALUES (1234); INSERT INTO table4 VALUES (1234); SELECT * FROM table1 t1; SELECT * FROM table2 t2; SELECT * FROM table2 t3; SELECT * FROM table2 t4; # SELECT * # FROM table1 t1 # FULL OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 # FULL OUTER JOIN table3 t3 ON t2.column_2 = t3.column_3 # FULL OUTER JOIN table4 t4 ON t3.column_3 = t4.column_4 # ORDER BY column_1, column_2, column_3, column_4; DROP VIEW IF EXISTS join_1_2 CASCADE; CREATE VIEW join_1_2 AS SELECT * FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2 WHERE t2.column_2 IS NULL UNION ALL SELECT * FROM table1 t1 RIGHT OUTER JOIN table2 t2 ON t1.column_1 = t2.column_2; DROP VIEW IF EXISTS join_1_2_3 CASCADE; CREATE VIEW join_1_2_3 AS SELECT * FROM join_1_2 t1 LEFT OUTER JOIN table3 t3 ON t1.column_2 = t3.column_3 WHERE t3.column_3 IS NULL UNION ALL SELECT * FROM join_1_2 t1 RIGHT OUTER JOIN table3 t3 ON t1.column_2 = t3.column_3; DROP VIEW IF EXISTS join_1_2_3_4 CASCADE; CREATE VIEW join_1_2_3_4 AS SELECT * FROM join_1_2_3 t1 LEFT OUTER JOIN table4 t4 ON t1.column_3 = t4.column_4 WHERE t4.column_4 IS NULL UNION ALL SELECT * FROM join_1_2_3 t1 RIGHT OUTER JOIN table4 t4 ON t1.column_3 = t4.column_4; SELECT * FROM join_1_2_3_4 ORDER BY column_1, column_2, column_3, column_4;
结论:
多个表的 FULL OUTER JOIN 可以拆分成多个 2 个表的 JOIN,中间结果可以使用 VIEW.