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 |
+----------------------+
联合表
从 MySQL 8.0.19 开始,您还可以
在
任何可以使用等效语句的地方使用TABLE
语句或
语句。假设表和
被创建和填充如下所示:
VALUES
UNION
SELECT
t1
t2
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);
如前所述,忽略以 开头的查询输出中的列名,
VALUES
以下所有
UNION
查询都会产生相同的结果:
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);
要强制列名相同,
VALUES
请将左侧的 包裹在 a 中
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 和 UNION ALL
默认情况下,重复行会从
UNION
结果中删除。optional
DISTINCT
关键字具有相同的效果,但使其显式化。使用可选ALL
关键字,不会发生重复行删除,结果包括所有
SELECT
语句中的所有匹配行。
您可以在同一个查询
中混合使用UNION
ALL
和。UNION
DISTINCT
处理混合
UNION
类型时,DISTINCT
联合会覆盖
ALL
其左侧的任何联合。DISTINCT
联合可以通过 using 显式生成,也可以通过不
带任何后续
关键字或关键字
的 usingUNION
DISTINCT
隐式
生成。UNION
DISTINCT
ALL
在 MySQL 8.0.19 及更高版本中,当在联合中使用一个或多个语句
时UNION ALL
,
工作方式相同。UNION DISTINCT
TABLE
联合中的 ORDER BY 和 LIMIT
要将ORDER BY
or
LIMIT
子句应用于 individual
SELECT
,
SELECT
请将 the 括起来并将子句放在括号内:
(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
for 单个
SELECT
语句并不意味着行在最终结果中出现的顺序,因为UNION
默认情况下会生成一组无序的行。因此,ORDER BY
在此上下文中通常与 结合使用
LIMIT
来确定要为 检索的所选行的子集
SELECT
,即使它不一定会影响这些行在最终
UNION
结果中的顺序。如果ORDER
BY
没有出现LIMIT
在 a 中
SELECT
,它会被优化掉,因为它在任何情况下都没有效果。
要使用ORDER BY
or
LIMIT
子句对整个
UNION
结果进行排序或限制,请将各个SELECT
语句括起来并将ORDER BY
or
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;
没有括号的语句等同于刚才显示的带括号的语句。
从 MySQL 8.0.19 开始,您可以按照刚才显示的相同方式在联合中使用ORDER
BY
and LIMIT
with
,请TABLE
记住TABLE
不支持WHERE
子句。
这种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;
要使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;
要另外维护单个结果中的排序顺序
,请向子句
SELECT
添加辅助列:ORDER BY
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)
UNION
(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col, col1a;
使用附加列还可以让您确定
SELECT
每一行来自哪一列。额外的列也可以提供其他标识信息,例如指示表名的字符串。
联合限制
在 aUNION
中,
SELECT
语句是普通的 select 语句,但有以下限制:
从 MySQL 8.0.20 开始,这两个
UNION
包含的变体
INTO
已被弃用,您应该期望在未来的 MySQL 版本中删除对它们的支持:
在查询表达式的尾随查询块中,使用
INTO
beforeFROM
会产生警告。例子:... UNION SELECT * INTO OUTFILE 'file_name' FROM table_name;
在查询表达式的带括号的尾随块中,使用
INTO
(无论其相对于 的位置如何FROM
)会产生警告。例子:... UNION (SELECT * INTO OUTFILE 'file_name' FROM table_name);
这些变体已被弃用,因为它们令人困惑,就好像它们从命名表而不是整个查询表达式 (the
UNION
) 中收集信息一样。
UNION
ORDER BY
子句中
带有聚合函数的查询会被ER_AGGREGATE_ORDER_FOR_UNION
错误拒绝。例子:
SELECT 1 AS foo UNION SELECT 2 ORDER BY MAX(1);
MySQL 8.0 中的 UNION 处理与 MySQL 5.7 的对比
在 MySQL 8.0 中,解析器规则
SELECT
和
UNION
被重构为更加一致(相同的SELECT
语法在每个这样的上下文中统一应用)并减少重复。与 MySQL 5.7 相比,这项工作产生了几个用户可见的效果,可能需要重写某些语句:
NATURAL JOIN
允许可选INNER
关键字 (NATURAL INNER JOIN
),符合标准 SQL。... JOIN ... JOIN ... ON ... ON
根据标准 SQL, 允许不带括号的右深度连接(例如, )。STRAIGHT_JOIN
现在允许一个USING
子句,类似于其他内部联接。解析器接受查询表达式周围的括号。例如,
(SELECT ... UNION SELECT ...)
是允许的。另见 第 13.2.10.6 节,“带括号的查询表达式”。解析器更好地符合文档中允许放置的
SQL_CACHE
和SQL_NO_CACHE
查询修饰符。联合的左侧嵌套,以前只允许在子查询中使用,现在可以在顶级语句中使用。例如,这个声明现在被认为是有效的:
(SELECT 1 UNION SELECT 1) UNION SELECT 1;
锁定子句 (
FOR UPDATE
,LOCK IN SHARE MODE
) 只允许在非UNION
查询中使用。这意味着括号必须用于SELECT
包含锁定子句的语句。此声明不再被接受为有效:SELECT 1 FOR UPDATE UNION SELECT 1 FOR UPDATE;
相反,写这样的声明:
(SELECT 1 FOR UPDATE) UNION (SELECT 1 FOR UPDATE);