踩坑MySQL UNION和ORDER BY混用的问题及解决
摘要
本文介绍MySQL中使用union多个子集导致排序失效的场景如何解决。
失效场景复现
目的
想先让A表按id升序,再让B表按id降序,然后拼在一起,最终想保证顺序一致
(SELECT id, name FROM A ORDER BY id ASC) UNION (SELECT id, name FROM B ORDER BY id DESC);
结果
A或B内单独查询顺序无误,但UNION后排序反而乱了…
原因
mysql8.0官方给的解释是:UNION分支里的ORDER BY会被优化器直接扔掉,想让单个分支先排好序,必须在该分支里再加一个LIMIT任意大数,并且最后把整个UNION再包一层SELECT,在最外层写ORDER BY。
正确写法
- 多子集排序字段一致:
SELECT * FROM ( SELECT id, name, 1 AS seq -- 用常量列保住先后顺序 FROM A ORDER BY id ASC LIMIT 99999999 -- 必须加LIMIT,否则ORDER BY会被优化掉 ) a UNION SELECT * FROM ( SELECT id, name, 2 AS seq FROM B ORDER BY id DESC LIMIT 99999999 ) b ORDER BY seq, id; -- 外层再按需要整体排序
- 多子集排序字段不一致:
SELECT * FROM ( SELECT id, create_time, 1 AS seq -- 用常量列保住先后顺序 FROM table_A ORDER BY create_time ASC LIMIT 99999999 -- 必须加LIMIT,否则ORDER BY会被优化掉 ) a UNION ( SELECT id, create_time, 2 AS seq FROM table_B ORDER BY id DESC LIMIT 99999999 ) b ORDER BY seq; -- 仅保证先A后B,不再对内部二次排序
总结
以上我们了解了mysql中union多个子集时防止子集内的排序失效的做法,子集写limit,外层再包含,最终再order。
这些仅为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
MySQL中length()、char_length()的区别
在MySQL中length(str)、char_length(str)都属于判断长度的内置函数,本文主要介绍了MySQL中length()、char_length()的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2023-05-05
Mysql数据库中datetime、bigint、timestamp来表示时间选择,谁来存储时间效率最高
这篇文章主要介绍了Mysql数据库中datetime、bigint、timestamp来表示时间选择,谁来存储时间效率最高,针对这一问题每人回答方式各不相同,下面分享下我的个人想法,需要的朋友可以参考下2021-08-08
MySQL之Innodb_buffer_pool_size设置方式
这篇文章主要介绍了MySQL之Innodb_buffer_pool_size设置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-08-08


最新评论