作者:张伟
爱可生北京分公司 DBA 团队成员,负责 MySQL 日常问题解决和 DMP 产品保护。青睐技术和开源数据库,青睐静止、读书、电影,花草树木。
本文起源:原创投稿
*爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。
一、UNION 的作用:
UNION 能够将多个 SELECT 查问语句的后果合并成一个后果集,在MySQL 8.0 中又削减了一些新的性能,咱们一起来看下。
二、UNION 操作符的花色展现:
1、温故
- Union 必须由两条或以上的 SELECT 语句组成,能力应用 Union 连贯。
- Union 中每个查问必须蕴含雷同数量的列或者聚合函数,列名或者别名须要统一。
- 列数据类型必须兼容,即能够进行隐式类型转换,但可能会呈现 SQL 性能问题,倡议数据类型雷同。
举例如下:
create table t1 (id int, name varchar(20));insert into t1 values(1,"爱可生"),(2,"开源"),(3,"社区"),(5,"MySQL"),(4,"张");create table t2 (id int, name varchar(20));insert into t2 values(3,"中国"),(11,"技术"),(15,"开源"),(2,"社区"),(1,"平凡"); mysql> select id from t1;+------+| id |+------+| 1 || 2 || 3 || 5 || 4 |+------+5 rows in set (0.00 sec) mysql> select id from t2;+------+| id |+------+| 3 || 11 || 15 || 2 || 1 |+------+5 rows in set (0.00 sec) // DISTINCT: 删除后果集中反复的数据。mysql> select id from t1 union distinct select id from t2;+------+| id |+------+| 1 || 2 || 3 || 5 || 4 || 11 || 15 |+------+7 rows in set (0.00 sec) // 默认状况下 UNION 操作符曾经删除了反复数据,所以 DISTINCT 修饰符对后果没啥影响。mysql> select id from t1 union select id from t2;+------+| id |+------+| 1 || 2 || 3 || 5 || 4 || 11 || 15 |+------+7 rows in set (0.00 sec) // ALL: 返回包含反复数据在内的所有后果集。mysql> select id from t1 union all select id from t2;+------+| id |+------+| 1 || 2 || 3 || 5 || 4 || 3 || 11 || 15 || 2 || 1 |+------+10 rows in set (0.00 sec)
应用 Union 组合查问时,只能应用一条 order by 子句对后果集进行排序,而且必须呈现在最初一条呈现的 SELECT 语句之后。因为 Union 不容许对于局部后果集进行排序,只能针对最终检索进去的后果集进行排序。
留神:因为在多表组合查问时候,可能表字段并不相同。所以在对于后果集排序的时候须要应用检索进去的独特字段。检索的字段 id 必须存在于后果集中。
举例如下:
2、知新
- 从 MySQL 8.0.19 版本开始,不仅在 SELECT 语句中,也能够在 TABLE 或 VALUES 语句中应用 UNION,只有能够应用等效的 SELECT 语句。
- 能够在 TABLE 中应用ORDER BY和LIMIT,但不反对WHERE子句。
- ORDER BY 不能应用蕴含 表名.列名 的援用。相同,在第一个 SELECT 语句中提供列别名,并在 ORDER BY 中援用别名。
- 如果要排序的列具备别名,ORDER BY 子句必须援用别名,而不是列名。
举例如下:
// 新增 table 语句的应用,因为取的是全表,对于繁多字段的去重就不便应用了mysql> table t1 union select * from t2;+------+-----------+| id | name |+------+-----------+| 1 | 爱可生 || 2 | 开源 || 3 | 社区 || 5 | MySQL || 4 | 张 || 3 | 中国 || 11 | 技术 || 15 | 开源 || 2 | 社区 || 1 | 平凡 |+------+-----------+10 rows in set (0.01 sec) // 新增 values 语句的应用,但会导致字段名生效mysql> values row(15,'开源') union select * from t2;+----------+----------+| column_0 | column_1 |+----------+----------+| 15 | 开源 || 3 | 中国 || 11 | 技术 || 2 | 社区 || 1 | 平凡 |+----------+----------+5 rows in set (0.01 sec) // 应用table 语句和values 语句的联合mysql> values row(15,'开源'),row(13,'北京') union table t2;+----------+----------+| column_0 | column_1 |+----------+----------+| 15 | 开源 || 13 | 北京 || 3 | 中国 || 11 | 技术 || 2 | 社区 || 1 | 平凡 |+----------+----------+6 rows in set (0.01 sec) // 如果定义字段名能够应用以下办法mysql > select * from (values row(15,'开源'),row(13,'北京')) AS t(c1,c2) union table t2;+------+--------+| c1 | c2 |+------+--------+| 15 | 开源 || 13 | 北京 || 3 | 中国 || 11 | 技术 || 2 | 社区 || 1 | 平凡 |+------+--------+6 rows in set (0.02 sec)
三、比照 MySQL 8.0 和 5.7 对 union 的解决
在 MySQL 8.0 中,对 SELECT 和 UNION 的解析器规定被重构进而变得更加统一,且缩小了反复。
与 MySQL 5.7 相比,某些语句可能须要重写:
- 比照规范 SQL , NATURAL JOIN 容许一个可选的 INNER 关键字(NATURAL INNER JOIN)。
- 比照规范 SQL ,能够应用不带括号的 Right-deep JOIN(例如,…JOIN…JOIN…ON…ON)。
- 与其余 INNER JOIN 相似,STRAIGHT_JOIN 当初容许 USING 子句。
- 解析器承受查问表达式四周的括号。例如:(SELECT ... UNION SELECT…)。
- 以前只容许在子查问中应用 union 的左嵌套,当初容许顶层语句中应用。如:(SELECT 1 UNION SELECT 1) UNION SELECT 1 ;
- 蕴含锁定子句的 SELECT 语句必须应用括号。例如:SELECT 1 FOR UPDATE UNION SELECT 1 FOR UPDATE; 变更为 (SELECT 1 FOR UPDATE) UNION (SELECT 1 FOR UPDATE);
四、参考文档:
https://dev.mysql.com/doc/ref...