源自MySQL 5.7 官方手冊:13.2.9.3 UNION Syntax
一、UNION語法
UNION用於將多個SELECT語句的結果合並到一個結果集中。
SELECT ... UNION [ALL | DISTINCT] SELECT ... [UNION [ALL | DISTINCT] SELECT ...]
將會使用第一個SELECT語句中的列名稱作為返回結果的列名稱。而且在每個SELECT語句的相應位置中列出的選定列應具有相同的數據類型。
如果相應SELECT列的數據類型不匹配,則UNION結果中列的類型和長度會考慮所有SELECT語句檢索的值。示例如下:
mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10); /* +---------------+ | REPEAT('a',1) | +---------------+ | a | | bbbbbbbbbb | +---------------+ */
UNION涉及到的SELECT語句有如下限制:
- 只有最后一個SELECT語句可以使用INTO OUTFILE,當然,全部UNION的結果會寫到文件中去。
- HIGH_PRIORITY在UNION語句中使用沒有意義。因為對第一個SELECT使用,不產生什么影響。在其它的SELECT中使用,會報錯。
UNION的默認會從結果中刪除重復的行,所以DINSTINCT關鍵字用不用都一樣。而ALL關鍵字就可以讓結果包含所有符合條件的重復行。
可以在同一查詢中混合使用UNION ALL和UNION DISTINCT。MySQL對此的處理策略是:一個DISTINCT UNION句覆蓋它其左側的任何ALL UINON句。
要將ORDER BY或LIMIT應用於單個SELECT,請將子句放在包含SELECT的括號內:
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10) UNION (SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
在5.7中,括號是必須的。
對UNION中的單個SELECT語句使用ORDER BY並不影響行在最終結果中出現的順序,因為UNION默認生成一組無序行。因此,在此上下文中使用ORDER BY通常與LIMIT結合使用來獲取一個子集。
如果在SELECT中沒有LIMIT出現ORDER BY,它會被優化掉,因為它無論如何都不會產生任何影響。
若要對整個UNION的結果使用ORDER BY 或 LIMIT,使用括號把SELECT子句括起來,然后在最后一個SELECT子句后使用他們。如下:
(SELECT a FROM t1 WHERE a=10 AND B=1) UNION (SELECT a FROM t2 WHERE a=11 AND B=2) ORDER BY a LIMIT 10;
這里如果不使用括號,他們估計會被應用在最后一個SELECT子句上。
對UNION結果使用的ORDER BY,不能使用tb1_name.col_name形式的列引用。而是在第一個SELECT語句中提供列別名,並引用ORDER BY中的別名
此外,如果要進行排序的列擁有別名,則ORDER BY子句必須引用別名,而不是列名。下面的第一個條SQL會正常運行,但是第二條SQL會失敗報錯:Unknow column 'a' in order clause。
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b; (SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a;
如果想讓UNION的結果,按查詢語句中所列的SELECT語句的順序一樣進行排列,可以為每個SELECT語句添加一個附加(常數)列作為專門的排序列,並在最后一個SELECT后添加ORDER BY。做法如下:
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1) UNION (SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col;
然后可以繼續在ORDER BY后添加輔助排序列了,這意味着來自同一個SELECT語句的數據行按輔助排序行進行排序:
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1) UNION (SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col, col1a;
附加列也可以提供其他標識信息,例如表名的字符串。
在ORDER BY子句中使用聚合函數的UNION查詢將被拒絕,並報出ER_AGGREGATE_ORDER_FOR_UNION錯誤。