当前位置: 代码网 > it编程>数据库>Mysql > mysql中union关键字的实现示例

mysql中union关键字的实现示例

2026年02月04日 Mysql 我要评论
mysql 的 union 用于合并两个或多个 select 语句的结果集,并自动去除重复行(相当于对结果集执行 distinct)。1. 基本语法与核心规则select column1, colum

mysql 的 union 用于合并两个或多个 select 语句的结果集,并自动去除重复行(相当于对结果集执行 distinct)。

1. 基本语法与核心规则

select column1, column2 from table1
union [all | distinct]
select column1, column2 from table2;

强制性规则

  • 列数必须相同:两个 select 返回的列数必须一致
  • 数据类型兼容:对应位置的列类型不必完全相同,但必须可隐式转换(如 int 和 decimal)
  • 列名继承:结果集的列名取自第一个 select 语句
  • order by 位置:只能放在最后一个 select 之后,且排序依据必须是第一个 select 的列名或别名

2. union vs union all

特性union (distinct)union all
去重自动去重,行唯一保留所有行,包括重复
性能需要临时表+哈希排序去重,较慢直接追加结果,极快
使用场景必须确保唯一性时确定无重复或需要保留重复时

性能建议:除非业务需要去重,否则优先使用 union all。去重操作需要创建临时表、哈希比较和额外排序,大数据量时性能差距巨大。

3. 实际应用场景

场景 a:合并相似结构表(如分表)

-- 查询 2023 和 2024 年的订单(假设按年分表)
select order_id, amount, created_at from orders_2023
union all
select order_id, amount, created_at from orders_2024
order by created_at desc
limit 20;

场景 b:多维度统计报表

select 'vip用户' as user_type, count(*) as cnt from users where level >= 8
union all
select '普通用户', count(*) from users where level between 1 and 7
union all
select '访客', count(*) from users where level = 0;

场景 c:数据补全与兜底查询

-- 先查缓存表,若无结果再查主表(常见于配置表)
select config_value from config_cache where config_key = 'site_name'
union all
select config_value from config where config_key = 'site_name'
limit 1;

4. 进阶用法

带排序和分页

(select id, name from products where category = 'a' order by price desc limit 10)
union all
(select id, name from products where category = 'b' order by price desc limit 10)
order by price desc limit 10;

注意:子查询中的 order by 必须配合 limit 才生效,否则会被优化器忽略。

混合聚合与明细

select city, sales_amount, null as detail from sales_summary
union all
select city, amount, concat(product_name, ':', quantity) from sales_detail;

5. 性能优化要点

  1. 索引利用:每个 select 独立使用索引,union 本身不走索引
  2. 减少数据集:在子查询中先 where 过滤,避免传递大量数据到 union 层
  3. 避免临时表写入union distinct 会创建内存临时表(或磁盘临时表,若过大),可通过 set tmp_table_size 调优
  4. 并行执行:mysql 8.0.19+ 对非相关子查询的 union 可能启用并行查询

6. 常见陷阱

-- ❌ 错误:列数不匹配
select id, name from t1
union
select id from t2;  -- error 1222

-- ❌ 错误:order by 位置错误
select * from t1 order by id
union
select * from t2;  -- error 1221

-- ✅ 正确写法
select * from t1
union
select * from t2
order by id;  -- 使用第一个 select 的列名排序

7. django orm 中的 union

如果你在使用 django(看你之前关注过 django 源码),可以这样使用:

from django.db.models import q

# queryset.union() 默认使用 union all
qs1 = user.objects.filter(status='active').values('name', 'email')
qs2 = user.objects.filter(is_staff=true).values('name', 'email')

# union all
combined = qs1.union(qs2, all=true)

# union (去重)
combined_distinct = qs1.union(qs2)  # 或 all=false

注意:django 的 union() 会强制转换为 sql 的 union,且 queryset 被求值后返回的是列表而非 queryset,无法继续链式过滤。

总结union all 是合并结果集的高性能首选,union (distinct) 仅在需要去重时使用。始终确保子查询列数一致,并在应用层处理复杂的排序逻辑。

到此这篇关于mysql中union关键字的实现示例的文章就介绍到这了,更多相关mysql union关键字内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com