我的编程空间,编程开发者的网络收藏夹
学习永远不晚

union和子查询中orderby一起使用导致排序失效问题及解决

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

union和子查询中orderby一起使用导致排序失效问题及解决

一、前言

分页查询的需求如同家常便饭,多数情况下主要利用order bylimit即可实现,有些稍复杂一点的可能需要用到union操作去连接多个子查询结果集。

然而这三个操作是有一些需要留意的问题,下文将列举出3个可能碰到的情况。

MySQL版本:5.7.21

二、问题列举

2.1 子查询中不能使用order by

简单的union操作如下:

SELECT * FROM tb_artist WHERE id >= 10
UNION
SELECT * FROM tb_artist WHERE id < 10

其结果为:

若子查询中包含order by,写法假设如下:

SELECT * FROM tb_artist WHERE id >= 10 ORDER BY id DESC
UNION
SELECT * FROM tb_artist WHERE id < 10

则语法报错:1221 - Incorrect usage of UNION and ORDER BY

应当将子查询括起来,正确写法如下:

(SELECT * FROM tb_artist WHERE id >= 10 ORDER BY id DESC)
UNION
(SELECT * FROM tb_artist WHERE id < 10)

其结果为:

语法没问题了,但是注意到子查询的order by却没有效果,故引出下面第二种问题。

2.2 子查询order by无效

解决方式是在子查询的order by后添加limit操作即可,具体可以limit一个不小于子查询结果集大小的数值,如下:

(SELECT * FROM tb_artist WHERE id >= 10 ORDER BY id DESC LIMIT 99999)
UNION
(SELECT * FROM tb_artist WHERE id < 10)

其结果为:

2.3 排序条件不够严格导致分页数据重复

该问题与union无直接联系,属于order bylimit本身的注意点。

即,如果SQL中的order by条件比较宽松不够严格,或者说是结果集中的每行记录存在并列或不唯一的次序的话,MySQL可能会随机给并列记录行进行排序,特别是排序又分页查询配合了limit操作,可能会导致上一页有的记录行又出现在了下一页的结果集之中。

对一些后台系统的分页表格中可能感觉不明显,但对于同样SQL查询逻辑的C端下拉列表的效果一目了然,特别是对带有图片的,很容易看到数据的重复。

解决方案:

所以在做分页查询时,要尽量保证每行记录都有唯一确定的次序,具体做法可以在原有排序条件后添加id或编号等这类唯一值的字段(索引字段也可以)。

例如,在艺术家artist创建时间降序排序的基础上,再对唯一code进行排序:

SELECT * FROM tb_artist WHERE logic_delete = 0 
ORDER BY 
	create_time DESC, 
	code ASC 
LIMIT 0, 5

原因分析:

排序离不开算法,在关系型数据库中,往往会存在多种排序算法。通过MySQL的源码和官方文档介绍可以得知,它的排序规律可以总结如下:

  • order by不能使用索引进行排序时,将使用排序算法进行排序;
  • 若排序内容能全部放入内存,则仅在内存中使用快速排序;
  • 若排序内容不能全部放入内存,则分批次将排好序的内容放入文件,然后将多个文件进行归并排序;
  • 若排序中包含limit语句,则使用堆排序(不稳定)优化排序过程。

所以解决排序分页数据重复问题有两种方式,第一种就是,在排序中加上唯一值,比如主键 id,这样由于 id 是唯一的,就能确保参与排序的 key 值不相同;第二种就是避免使用堆排序,让order by根据索引来排序。

说白了,就是order by后面的字段要有索引。

另外,使用JPA分页查询时,若order by的是非索引字段,通过查看JPA的sql发现,不会再去自动在order by后添加索引或id字段,需要注意。

MySQL5.7 相关文档:

https://dev.mysql.com/doc/refman/5.7/en/union.html

https://dev.mysql.com/doc/refman/5.7/en/order-by-optimization.html

https://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

union和子查询中orderby一起使用导致排序失效问题及解决

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

union和子查询中orderby一起使用导致排序失效问题及解决

这篇文章主要介绍了union和子查询中orderby一起使用导致排序失效问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2022-12-27

union和子查询中order by一起使用导致排序失效问题及解决

目录一、前言二、问题列举2.1 子查询中不能使用order by2.2 子查询order by无效2.3 排序条件不够严格导致分页数据重复总结一、前言分页查询的需求如同家常便饭,多数情况下主要利用order by和limit即可实现,有些
2022-12-27

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录