MySQL⼦查询中orderby不⽣效问题的解决⽅法
⼀个偶然的机会,发现⼀条SQL语句在不同的MySQL实例上执⾏得到了不同的结果。
问题描述
创建商品表product_tbl和商品操作记录表product_operation_tbl两个表,来模拟下业务场景,结构和数据如下:
接下来需要查询所有商品最新的修改时间,使⽤如下语句:
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操作,进⽽查询出的商品的最新修改时间。
在区域A的MySQL实例上,查询商品最新修改时间可以得到正确结果,但是在区域B的MySQL实例上,得到的修改时间并不是最新的,⽽是最⽼的。通
过对语句进⾏简化,发现是⼦查询中的order by created_at desc语句在区域B的实例上没有⽣效。
排查过程
难道区域会影响MySQL的⾏为?经过DBA排查,区域A的MySQL是5.6版,区域B的MySQL是5.7版,并且到了这篇⽂章:
根据⽂章的描述,MySQL 5.7版会忽略掉⼦查询中的order by语句,可令⼈疑惑的是,我们模拟业务场景的MySQL是8.0版,并没有出现这个问题。使⽤docker分别启动MySQL 5.6、5.7、8.0三个实例,来重复上⾯的操作,结果如下:
可以看到,只有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 ignor
e 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不⽣效内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!mysql下载不了什么原因
参考⽂档

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。