MySQL子查询中order by不生效问题的解决方法


Posted in MySQL onAugust 02, 2021

一个偶然的机会,发现一条SQL语句在不同的MySQL实例上执行得到了不同的结果。

问题描述

创建商品表product_tbl和商品操作记录表product_operation_tbl两个表,来模拟下业务场景,结构和数据如下:

MySQL子查询中order by不生效问题的解决方法

MySQL子查询中order by不生效问题的解决方法

接下来需要查询所有商品最新的修改时间,使用如下语句:

select t1.id, t1.name, t2.product_id, t2.created_at  from product_tbl t1 left join (select * from product_operation_log_tbl order by created_at desc) t2 on t1.id = t2.product_id group by t1.id;

通过结果可以看到,子查询先将product_operation_log_tbl里的所有记录按创建时间(created_at)逆序,然后和product_tbl进行join操作,进而查询出的商品的最新修改时间。

MySQL子查询中order by不生效问题的解决方法

在区域A的MySQL实例上,查询商品最新修改时间可以得到正确结果,但是在区域B的MySQL实例上,得到的修改时间并不是最新的,而是最老的。通过对语句进行简化,发现是子查询中的order by created_at desc语句在区域B的实例上没有生效。

排查过程

难道区域会影响MySQL的行为?经过DBA排查,区域A的MySQL是5.6版,区域B的MySQL是5.7版,并且找到了这篇文章:

https://blog.csdn.net/weixin_42121058/article/details/113588551

根据文章的描述,MySQL 5.7版会忽略掉子查询中的order by语句,可令人疑惑的是,我们模拟业务场景的MySQL是8.0版,并没有出现这个问题。使用docker分别启动MySQL 5.6、5.7、8.0三个实例,来重复上面的操作,结果如下:

MySQL子查询中order by不生效问题的解决方法

可以看到,只有MySQL 5.7版忽略了子查询中的order by。有没有可能是5.7引入了bug,后续版本又修复了呢?

问题根因

继续搜索文档和资料,发现官方论坛中有这样一段描述:

A "table" (and subquery in the FROM clause too) is - according to the SQL standard - an unordered set of rows. Rows in a table (or in a subquery in the FROM clause) do not come in any specific order. That's why the optimizer can ignore the ORDER BY clause that you have specified. In fact, SQL standard does not even allow the ORDER BY clause to appear in this subquery (we allow it, because ORDER BY ... LIMIT ... changes the result, the set of rows, not only their order). You need to treat the subquery in the FROM clause, as a set of rows in some unspecified and undefined order, and put the ORDER BY on the top-level SELECT.

问题的原因清晰了,原来SQL标准中,table的定义是一个未排序的数据集合,而一个SQL子查询是一个临时的table,根据这个定义,子查询中的order by会被忽略。同时,官方回复也给出了解决方案:将子查询的order by移动到最外层的select语句中。

总结

在SQL标准中,子查询中的order by是不生效的

MySQL 5.7由于在这个点上遵循了SQL标准导致问题暴露,而在MySQL 5.6/8.0中这种写法依然是生效的

到此这篇关于MySQL子查询中order by不生效问题的文章就介绍到这了,更多相关MySQL子查询order by不生效内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

参考文档

https://stackoverflow.com/questions/26372511/mysql-mariadb-order-by-inside-subquery

https://mariadb.com/kb/en/why-is-order-by-in-a-from-subquery-ignored/

 

MySQL 相关文章推荐
MySQL pt-slave-restart工具的使用简介
Apr 07 MySQL
MySQL8.0.24版本Release Note的一些改进点
Apr 22 MySQL
浅谈Mysql多表连接查询的执行细节
Apr 24 MySQL
MySQL中你可能忽略的COLLATION实例详解
May 12 MySQL
详解MySQL中的pid与socket
Jun 15 MySQL
mysql的数据压缩性能对比详情
Nov 07 MySQL
MySQL中IO问题的深入分析与优化
Apr 02 MySQL
解决MySQL Varchar 类型尾部空格的问题
Apr 06 MySQL
MySQL 计算连续登录天数
May 11 MySQL
MySQL详解进行JDBC编程与增删改查方法
Jun 16 MySQL
MySQL中LAG()函数和LEAD()函数的使用
Aug 14 MySQL
SQLyog的下载、安装、破解、配置教程(MySQL可视化工具安装)
Sep 23 MySQL
MySQL中utf8mb4排序规则示例
Aug 02 #MySQL
MySql子查询IN的执行和优化的实现
MySQL里面的子查询的基本使用
Aug 02 #MySQL
Centos7中MySQL数据库使用mysqldump进行每日自动备份的编写
Aug 02 #MySQL
为什么MySQL选择Repeatable Read作为默认隔离级别
使用ORM新增数据在Mysql中的操作步骤
Jul 26 #MySQL
mysql脏页是什么
Jul 26 #MySQL
You might like
php+highchats生成动态统计图
2014/05/21 PHP
php邮件发送的两种方式
2020/04/28 PHP
php获取图片信息的方法详解
2015/12/10 PHP
jQuery 工具函数学习资料
2010/04/29 Javascript
jquery插件制作 提示框插件实现代码
2012/08/17 Javascript
jquery使用ul模拟select实现表单美化的方法
2015/08/18 Javascript
jQuery EasyUI之DataGrid使用实例详解
2016/01/04 Javascript
jQuery中Find选择器用法示例
2016/09/21 Javascript
jquery实现简单的瀑布流布局
2016/12/11 Javascript
Bootstrap CSS组件之大屏幕展播
2016/12/17 Javascript
详解nodejs 文本操作模块-fs模块(三)
2016/12/22 NodeJs
原生js编写2048小游戏
2017/03/17 Javascript
nodejs后台集成ueditor富文本编辑器的实例
2017/07/11 NodeJs
node.js+captchapng+jsonwebtoken实现登录验证示例
2017/08/17 Javascript
JS常用的几种数组遍历方式以及性能分析对比实例详解
2018/04/11 Javascript
vue+element-ui+axios实现图片上传
2019/08/20 Javascript
layui前端时间戳转化实例
2019/11/15 Javascript
如何利用JS将手机号中间四位变成*号
2020/09/29 Javascript
[03:55]DOTA2完美大师赛选手传记——LFY.MONET
2017/11/18 DOTA
Python入门之三角函数tan()函数实例详解
2017/11/08 Python
Python数据可视化编程通过Matplotlib创建散点图代码示例
2017/12/09 Python
Python 实现字符串中指定位置插入一个字符
2018/05/02 Python
Python使用try except处理程序异常的三种常用方法分析
2018/09/05 Python
python按键按住不放持续响应的实例代码
2019/07/17 Python
python3 dict ndarray 存成json,并保留原数据精度的实例
2019/12/06 Python
Kipling意大利官网:世界著名的时尚休闲包袋品牌
2019/06/05 全球购物
空指针到底是什么
2012/08/07 面试题
在对linux系统分区进行格式化时需要对磁盘簇(或i节点密度)的大小进行选择,请说明选择的原则
2012/11/24 面试题
计算机专业学生求职信分享
2013/12/15 职场文书
逃课上网检讨书
2014/02/20 职场文书
毕业生简历自我评价范文
2014/04/09 职场文书
工作岗位说明书模板
2014/05/09 职场文书
单位承诺书格式
2014/05/21 职场文书
新闻编辑求职信
2014/07/13 职场文书
《家世》读后感:看家训的力量
2019/12/30 职场文书
详解pytorch创建tensor函数
2022/03/22 Python