13.2.10.3 UNION ClauseUNION子句

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

UNION combines the result from multiple SELECT statements into a single result set. UNION将多个SELECT语句的结果合并到一个结果集中。Example:例如:

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 |
+---+---+
Result Set Column Names and Data Types结果集列名和数据类型

The column names for a UNION result set are taken from the column names of the first SELECT statement.UNION结果集的列名取自第一条SELECT语句的列名。

Selected columns listed in corresponding positions of each SELECT statement should have the same data type. 在每个SELECT语句的相应位置列出的选定列应具有相同的数据类型。For example, the first column selected by the first statement should have the same type as the first column selected by the other statements. 例如,第一条语句选择的第一列应该与其他语句选择的第一列具有相同的类型。If the data types of corresponding SELECT columns do not match, the types and lengths of the columns in the UNION result take into account the values retrieved by all the SELECT statements. 如果相应SELECT列的数据类型不匹配,UNION结果中列的类型和长度将考虑所有SELECT语句检索到的值。For example, consider the following, where the column length is not constrained to the length of the value from the first SELECT:例如,考虑以下情况,其中列长度不受来自第一个SELECT的值的长度的约束:

mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',20);
+----------------------+
| REPEAT('a',1)        |
+----------------------+
| a                    |
| bbbbbbbbbbbbbbbbbbbb |
+----------------------+
TABLE in Unions联合中的表

Beginning with MySQL 8.0.19, you can also use a TABLE statement or VALUES statement in a UNION wherever you can employ the equivalent SELECT statement. 从MySQL 8.0.19开始,您还可以在UNION中使用TABLE语句或VALUES语句,只要您可以使用等效的SELECT语句。Assume that tables t1 and t2 are created and populated as shown here:假设表t1t2的创建和填充如下所示:

CREATE TABLE t1 (x INT, y INT);
INSERT INTO t1 VALUES ROW(4,-2),ROW(5,9);

CREATE TABLE t2 (a INT, b INT);
INSERT INTO t2 VALUES ROW(1,2),ROW(3,4);

The preceding being the case, and disregarding the column names in the output of the queries beginning with VALUES, all of the following UNION queries yield the same result:在前面的情况下,忽略以VALUES开头的查询输出中的列名,以下所有联合查询都会产生相同的结果:

SELECT * FROM t1 UNION SELECT * FROM t2;
TABLE t1 UNION SELECT * FROM t2;
VALUES ROW(4,-2), ROW(5,9) UNION SELECT * FROM t2;
SELECT * FROM t1 UNION TABLE t2;
TABLE t1 UNION TABLE t2;
VALUES ROW(4,-2), ROW(5,9) UNION TABLE t2;
SELECT * FROM t1 UNION VALUES ROW(4,-2),ROW(5,9);
TABLE t1 UNION VALUES ROW(4,-2),ROW(5,9);
VALUES ROW(4,-2), ROW(5,9) UNION VALUES ROW(4,-2),ROW(5,9);

To force the column names to be the same, wrap the VALUES on the left hand side in a SELECT and use aliases, like this:要强制列名相同,请将左侧的VALUES包装在一个SELECT中,并使用别名,如下所示:

SELECT * FROM (VALUES ROW(4,-2), ROW(5,9)) AS t(x,y)
  UNION TABLE t2;
SELECT * FROM (VALUES ROW(4,-2), ROW(5,9)) AS t(x,y)
  UNION VALUES ROW(4,-2),ROW(5,9);
UNION DISTINCT and UNION ALL

By default, duplicate rows are removed from UNION results. 默认情况下,将从UNION结果中删除重复的行。The optional DISTINCT keyword has the same effect but makes it explicit. 可选的DISTINCT关键字具有相同的效果,但使其显式。With the optional ALL keyword, duplicate-row removal does not occur and the result includes all matching rows from all the SELECT statements.使用可选的ALL关键字时,不会删除重复行,并且结果包括所有SELECT语句中的所有匹配行。

You can mix UNION ALL and UNION DISTINCT in the same query. 可以在同一查询中混合使用UNION ALLUNION DISTINCTMixed UNION types are treated such that a DISTINCT union overrides any ALL union to its left. 混合UNION类型的处理方式是,不同的联合会覆盖其左侧的所有联合。A DISTINCT union can be produced explicitly by using UNION DISTINCT or implicitly by using UNION with no following DISTINCT or ALL keyword.可以通过使用UNION DISTINCT显式生成DISTINCT联合,也可以通过使用UNION(不带DISTINCTALL关键字)隐式生成DISTINCT联合。

In MySQL 8.0.19 and later, UNION ALL and UNION DISTINCT work the same way when one or more TABLE statements are used in the union.在MySQL8.0.19及更高版本中,UNION ALLUNION DISTINCTUNION中使用一个或多个TABLE语句时的工作方式相同。

ORDER BY and LIMIT in Unions联合中的ORDER BY和LIMIT

To apply an ORDER BY or LIMIT clause to an individual SELECT, parenthesize the SELECT and place the clause inside the parentheses:要将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);

Use of ORDER BY for individual SELECT statements implies nothing about the order in which the rows appear in the final result because UNION by default produces an unordered set of rows. 对单个SELECT语句使用ORDER BY并不表示行在最终结果中的显示顺序,因为UNION在默认情况下会生成一组无序的行。Therefore, ORDER BY in this context typically is used in conjunction with LIMIT, to determine the subset of the selected rows to retrieve for the SELECT, even though it does not necessarily affect the order of those rows in the final UNION result. 因此,在这种情况下,ORDER BY通常与LIMIT一起使用,以确定要为SELECT检索的选定行的子集,即使它不一定影响这些行在最终联合结果中的顺序。If ORDER BY appears without LIMIT in a SELECT, it is optimized away because it has no effect in any case.如果ORDER BYSELECT中没有限制地出现,它将被优化掉,因为它在任何情况下都没有效果。

To use an ORDER BY or LIMIT clause to sort or limit the entire UNION result, parenthesize the individual SELECT statements and place the ORDER BY or LIMIT after the last one:要使用ORDER BYLIMIT子句对整个联合结果进行排序或限制,请将各个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;

A statement without parentheses is equivalent to one parenthesized as just shown.没有括号的语句相当于刚才显示的带括号的语句。

Beginning with MySQL 8.0.19, you can use ORDER BY and LIMIT with TABLE in unions in the same way as just shown, bearing in mind that TABLE does not support a WHERE clause.从MySQL8.0.19开始,您可以在联合中使用ORDER BYLIMIT配合TABLE,方法与刚才所示的相同,请记住TABLE不支持WHERE子句。

This kind of ORDER BY cannot use column references that include a table name (that is, names in tbl_name.col_name format). 这种ORDER BY不能使用包含表名的列引用(即tbl_name.col_name格式的名称)。Instead, provide a column alias in the first SELECT statement and refer to the alias in the ORDER BY. 相反,请在第一个SELECT语句中提供列别名,并在ORDER BY中引用别名。(Alternatively, refer to the column in the ORDER BY using its column position. (或者,使用列位置引用顺序中的列。However, use of column positions is deprecated.)但是,不推荐使用列位置。)

Also, if a column to be sorted is aliased, the ORDER BY clause must refer to the alias, not the column name. 另外,如果要排序的列具有别名,ORDER BY子句必须引用别名,而不是列名。The first of the following statements is permitted, but the second fails with an Unknown column 'a' in 'order clause' error:允许使用以下语句中的第一个语句,但第二个语句失败,出现“order子句”错误中的未知列“a”:

(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b;
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a;

To cause rows in a UNION result to consist of the sets of rows retrieved by each SELECT one after the other, select an additional column in each SELECT to use as a sort column and add an ORDER BY that sorts on that column following the last SELECT:要使UNION结果中的行由每个SELECT逐个检索的行集组成,请在每个SELECT中选择一个附加列作为排序列,并添加一个ORDER BY,在最后一个SELECT之后对该列进行排序:

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

To additionally maintain sort order within individual SELECT results, add a secondary column to the ORDER BY clause:若要在单个SELECT结果中另外维护排序顺序,请向ORDER BY子句中添加第二列:

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

Use of an additional column also enables you to determine which SELECT each row comes from. 使用附加列还可以确定每一行来自哪个SELECTExtra columns can provide other identifying information as well, such as a string that indicates a table name.额外的列还可以提供其他标识信息,例如表示表名的字符串。

UNION Restrictions限制

In a UNION, the SELECT statements are normal select statements, but with the following restrictions:UNION中,SELECT语句是正常的选择语句,但有以下限制:

As of MySQL 8.0.20, these two UNION variants containing INTO are deprecated and you should expect support for them to be removed in a future version of MySQL:从MySQL 8.0.20开始,这两个包含INTOUNION变体已被弃用,您应该希望在将来的MySQL版本中删除对它们的支持:

UNION queries with an aggregate function in an ORDER BY clause are rejected with an ER_AGGREGATE_ORDER_FOR_UNION error. ORDER BY子句中包含聚合函数的UNION查询将被拒绝,并出现ER_AGGREGATE_ORDER_FOR_UNION错误。Example:例如:

SELECT 1 AS foo UNION SELECT 2 ORDER BY MAX(1);
UNION Handing in MySQL 8.0 Compared to MySQL 5.7MySQL8.0与MySQL5.7中的UNION处理的比较

In MySQL 8.0, the parser rules for SELECT and UNION were refactored to be more consistent (the same SELECT syntax applies uniformly in each such context) and reduce duplication. 在MySQL 8.0中,SELECTUNION的解析器规则被重构为更加一致(相同的SELECT语法在每个这样的上下文中统一应用)并减少重复。Compared to MySQL 5.7, several user-visible effects resulted from this work, which may require rewriting of certain statements:与MySQL5.7相比,这项工作产生了一些用户可见的效果,可能需要重写某些语句: