13.2.9.3 UNION 子句

SELECT ...
UNION [ALL | DISTINCT] SELECT ...
[UNION [ALL | DISTINCT] SELECT ...]

UNION将多个SELECT语句的结果合并为一个结果集。例:

mysql> SELECT 1, 2;
+---+---+
| 1 | 2 |
+---+---+
| 1 | 2 |
+---+---+
mysql> SELECT 'a', 'b';
+---+---+
| a | b |
+---+---+
| a | b |
+---+---+
mysql> SELECT 1, 2 UNION SELECT 'a', 'b';
+---+---+
| 1 | 2 |
+---+---+
| 1 | 2 |
| a | b |
+---+---+
结果集列名称和数据类型

UNION结果集的列名取自第一个SELECT语句的列名。

每个SELECT语句的相应位置中列出的所选列应具有相同的数据类型。例如,第一条语句选择的第一列应与其他语句选择的第一列具有相同的类型。如果相应的SELECT列的数据类型不匹配,则UNION结果中的列的类型和长度将考虑所有SELECT语句检索到的值。例如,考虑以下情况,其中列长度不限于第一个SELECT的值的长度:

mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',20);
+----------------------+
| REPEAT('a',1)        |
+----------------------+
| a                    |
| bbbbbbbbbbbbbbbbbbbb |
+----------------------+
UNION DISTINCT 和 UNION ALL

默认情况下,重复的行将从UNION个结果中删除。可选的DISTINCT关键字具有相同的效果,但使它显式。使用可选的ALL关键字,不会发生重复行删除,并且结果包括所有SELECT语句中的所有匹配行。

您可以在同一查询中混合使用UNION ALLUNION DISTINCT。混合的UNION类型被处理为使得DISTINCT联合覆盖其左侧的任何ALL联合。可以通过使用UNION DISTINCT显式生成DISTINCT联合,也可以通过使用UNION隐式地创建DISTINCT联合,而没有后面的DISTINCTALL关键字。

联合1 ORDER BY 和 LIMIT

要将ORDER BYLIMIT子句应用于单个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);

Note

MySQL 的早期版本可能允许不带括号的此类语句。在 MySQL 5.7 中,强制使用括号。

对单个SELECT语句使用ORDER BY并不意味着行在最终结果中出现的 Sequences,因为UNION默认情况下会产生一组无序的行。因此,在这种情况下ORDER BY通常与LIMIT结合使用,以确定要为SELECT检索的所选行的子集,即使它不一定会影响最终UNION结果中这些行的 Sequences。如果_5 中的ORDER BY在_5 中没有LIMIT出现,则会对其进行优化,因为无论如何它都不会起作用。

要使用ORDER BYLIMIT子句对整个UNION结果进行排序或限制,请对单个SELECT语句加上括号,并将ORDER BYLIMIT放在最后一个语句之后:

(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;

如前所述,不带括号的语句等同于一个带括号的语句。

这种ORDER BY不能使用包含 table 名(即* 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;

要使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;

要另外在单个SELECT结果中保持排序 Sequences,请在ORDER BY子句中添加第二列:

(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)
UNION
(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col, col1a;

通过使用其他列,您还可以确定每行来自哪个SELECT。额外的列也可以提供其他标识信息,例如指示 table 名的字符串。

ORDER BY子句中具有聚合函数的UNION查询被拒绝,并出现ER_AGGREGATE_ORDER_FOR_UNION错误。例:

SELECT 1 AS foo UNION SELECT 2 ORDER BY MAX(1);
UNION Restrictions

UNION中,SELECT语句是普通的 select 语句,但具有以下限制:

  • SELECT个中的HIGH_PRIORITY无效。后续的SELECT中的HIGH_PRIORITY会产生语法错误。

  • 只有最后一个SELECT语句可以使用INTO子句。但是,整个UNION结果被写入INTO输出目的地。