MySQL子查询中order by失效问题

问题描述:

在编写SQL语句时需要对查询结果进行排序,如果子查询中可以先使用 order by 排序后再进行连接查询,和先进行连接查询后再对查询结果排序,这两种方式的效率是不一样的,明显前一种的效率高一些,而再MySQL 8.0版本以后,子查询的 order by 排序可能会失效。

官方论坛中有这样一段描述:

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语句中。

另一个原因:

文档链接:

8.2.2.1(官方文档)

8.2.2.1(中文文档 )

因为在mysql5.7中,系统会把order by优化掉。
在mysql5.7手册的8.2.2.1中有解释:
子查询的优化是使用半连接的策略完成的(The optimizer uses semi-join strategies to improve subquery execution)
使用半连接进行优化,子查询语句必须满足一些标准(In MySQL, a subquery must satisfy these criteria to be handled as a semi-join)。
其中一个标准是:必须不是一个包含了limit和order by的语句(It must not have ORDER BY with LIMIT.)

解决方案:

方案一(可能会失效):需要在我们 order by 的子查询中加上 limit 语句。

方案二:将子查询的order by移动到最外层的select语句中。

猜你喜欢

转载自blog.csdn.net/weixin_57542177/article/details/128266591