13.2.9.3 UNION 語法
SELECT …
UNION [ALL | DISTINCT] SELECT …
[UNION [ALL | DISTINCT] SELECT …]
UNION 作用是將多個select語句的結果整合到一個結果中返回。
以第一個select語句的列名稱作爲返回結果的列名稱,每個select語句對應列返回的數據類型應該一致。
如果數據類型不匹配,union結果會從所有的select語句中推測返回列的類型和長度。比如:
mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+---------------+
| REPEAT('a',1) |
+---------------+
| a |
| bbbbbbbbbb |
+---------------+
這是一個常見的select語句,但是有一下限制:
* 只有最後一個select語句能夠使用INTO OUTFILE(儘管是將整個union結果寫入到文件中)。
* HIGH_PRIORITY 語句不能在union中使用,如果你在第一個select語句中使用 HIGH_PRIORITY,實際上並不會起效。如果放到其他select語句中,則會報語法錯誤。
union默認會對返回結果去重,等同於union distinct。如果使用ALL關鍵字,將不會去重。
你可以同時在同一個查詢語句中使用UNION ALL 和 UNION DISTINCT,UNION DISTINCT語句會覆蓋出現在他前面的UNION ALL語句。
如果想對其中一個select語句使用ORDER BY 或 LIMIT,你需要將這個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);
儘管上面的例子可以使用,但ORDER BY的結果並不會影響最終的返回結果,因爲UNION產生的結果是一個無序集合。所以典型的使用ORDER BY場景是和LIMIT一塊使用的,用於只取一部分數據。如果ORDER BY沒有和LIMIT一塊使用,執行時優化器會去掉ORDER BY語句。
如果相對整個union結果使用ORDER BY 或 LIMIT,需要將每一個select語句括起來,最後加上ORDER BY 或 LIMIT:
(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語句沒有被括起來,等同於對單個語句使用ORDER BY 或 LIMIT。
這種方式的ORDER BY使用列,不用表明限定(tbl_name.col_name)。你需要對第一個select的列定義別名,然後order by中使用別名排序。(也可以order by 字段出現的位置,這種方式不建議使用)
如果一個要排序的列定義的別名,那麼ORDER BY只能使用別名,不能使用列名稱。下面的第一個列子可以執行,但是第二個會報“Unknown 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;
如果想讓返回結果中,後一個select的結果都在前一個select結構的後面,可以增加一個排序列,並按次列排序即可:
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)
UNION
(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col;
如果想進一步對select裏面的結果也有序,可以再增加一個排序列:
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)
UNION
(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col, col1a;
使用附加列可以讓你知道返回結果來源於那個select語句。額外的列也可以更好的聲明返回結果每一行的信息,比如增加一個表名稱的列。