SQL的union和union all

文章目录

环境

  • MySQL 8.0.28
  • CentOS 7.9

union和union all的区别

二者的区别在于是否去重。

  • union:去除重复记录
  • union all:只是简单的把两个结果集拼接在一起

例如,要统计两个网站的每天访问量:

sql 复制代码
select date, sum(amount) as amount from
(
(select date, count(*) as amount from website1
where id = 123
group by date)
union all
(select date, count(*) as amount from website2
where id = 123
group by date)
) as total
group by date

本例中,不能去重(因为可能两个网站的date和amount恰好都一样),所以使用 union all 。

再例如,要统计一个名单,包含身高最高和体重最重的人员信息:

sql 复制代码
(select name from t1 order by height desc limit 1)
union
(select name from t1 order by weight desc limit 1)

本例中,必须去重(因为只要一个名单),所以用 union 。

总结:

  • 使用 union 还是 union all ,基本上是由业务逻辑决定的(感觉 union all 的使用场景更多)。
  • 优先使用 union all ,因为它的效率更高。
  • 如果需要去重,当然应该用 union,不过如果确定子查询之间(以及子查询内部)没有重复记录,可以用 union all (慎用)。

子查询的括号

sql 复制代码
select * from t1 where id = 1
union all
select * from t2 where id = 2
sql 复制代码
(select * from t1 where id = 1)
union all
(select * from t2 where id = 2)

这两个SQL效果一样吗?

答案是一样的。

但是,如果子查询有 order by 、 limit 等条件时,必须用括号,否则会被当做全局的。

例如:

sql 复制代码
select * from t1 where id = 1
union all
select * from t2 where id = 2 limit 1

虽然看上去 limit 1 和第二个子查询在同一行,但它实际上是全局的,所以整个结果里只有一条记录。

再例如:

sql 复制代码
select * from t1 where id = 1 limit 1
union all
select * from t2 where id = 2

虽然看上去 limit 1 和第一个子查询在同一行,但它实际上是全局的,所以整个SQL语句有语法错误,无法运行。

再例如:

sql 复制代码
(select * from website1 where score > 0 order by date desc limit 1)
union all
(select * from website2 where score = 0 order by date desc limit 1)
order by score desc limit 1

这是一个正确的SQL语句。

总结:子查询最好用括号括起来,清晰明了。

union整体去重

我们知道,用 union 连接两个子查询时,会去除重复记录,那么问题来了,这里的"去重",只是针对两个子查询之间的重复记录吗?如果一个子查询本身就包含了重复记录,那么 union 之后会去重吗?

答案是,如果一个子查询本身包含了重复记录,那么 union 之后也会去重。

可以想象, union 是先 union all 把结果集拼接起来,然后再整体去重。

排序

以 union all 为例,它只是简单的拼接两个结果集,那么问题来了,如果没有全局的 order by ,那么最终的结果集是有顺序的吗?

答案是,不要依赖隐式排序,虽然在绝大多数情况下,结果集的顺序就是拼接的顺序,但是不能100%保证如此,所以,有需要时还是要用 order by 来保证顺序。

这就像 select * from t1 一样,虽然绝大多数情况下返回的顺序就是记录的自然顺序,但是保险起见,最好还是加上 order by 来保证顺序。

相关推荐
一只积极向上的小咸鱼14 小时前
第一性原理思考:从拆解问题到用实验检验答案
数据库
这个DBA有点耶14 小时前
时序数据库InfluxDB高基数问题深度拆解:内存索引膨胀机制与OOM完整链路
数据库·架构·dba
加油yx14 小时前
MySQL数据类型
数据库·mysql
蓝胖的四次元口袋15 小时前
Redis知识梳理(1)
数据库·redis·缓存
夜雪一千15 小时前
MySQL 数据加密实战:从传输、存储到字段级加密,分清场景不踩坑
数据库·mysql
wefg116 小时前
【Redis】C++ 自定义客户端
数据库·redis·缓存
这个DBA有点耶16 小时前
为什么UPDATE比SELECT危险得多?锁范围等于扫描行数
数据库·架构·代码规范
天国梦16 小时前
国密门禁品牌怎么选?2026年最新3个避坑要点
运维·服务器·数据库·python
DB哥讲数据库16 小时前
【达梦数据库安装教程】超详细图文讲解-附达梦安装包
数据库·oracle
Hoxy.R17 小时前
【金仓数据库产品体验官】KingbaseES V9R2C16 坏块检测与修复完整测试流程
数据库