且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

MySQL/MariaDB - 按内部子查询排序

更新时间:2023-02-24 22:10:40

经过一番挖掘,我可以确认您的两种情况:

After a bit of digging, I can confirm both your scenarios:

MySQL 5.1 确实在子查询中应用了 ORDER BY.

MySQL 5.1 does apply the ORDER BY inside the subquery.

Linux 上的 MariaDB 5.5.39 不会在未提供 LIMIT 的子查询中应用 ORDER BY.当给出相应的 LIMIT 时,它确实正确地应用了顺序:

MariaDB 5.5.39 on Linux does not apply the ORDER BY inside the subquery when no LIMIT is supplied. It does however correctly apply the order when a corresponding LIMIT is given:

SELECT t2.Code 
FROM (
  SELECT Country.Code FROM Country ORDER BY Country.Code DESC LIMIT 2
) AS t2;

如果没有 LIMIT,就没有充分的理由在子查询中应用排序.它可以等效地应用于外部查询.

Without that LIMIT, there isn't a good reason to apply the sort inside the subquery. It can be equivalently applied to the outer query.

事实证明,MariaDB 已经记录了这种行为 并且它不被视为错误:

As it turns out, MariaDB has documented this behavior and it is not regarded as a bug:

一个桌子"(以及 FROM 子句中的子查询也是) - 根据 SQL 标准 - 一组无序的行.表中的行(或 FROM 子句中的子查询)没有任何特定的顺序.这就是优化器可以忽略您指定的 ORDER BY 子句的原因.事实上,SQL 标准甚至不允许 ORDER BY 子句出现在这个子查询中(我们允许它,因为 ORDER BY ... LIMIT ... 改变了结果, 行的集合,不仅是它们的顺序).

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).

您需要将 FROM 子句中的子查询视为一组未指定和未定义顺序的行,并将 ORDER BY 放在***SELECT.

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.

因此 MariaDB 还建议在最外层查询中应用 ORDER BY,或者在必要时应用 LIMIT.

So MariaDB also recommends applying the ORDER BY in the outermost query, or a LIMIT if necessary.

注意:我目前无法访问合适的 MySQL 5.5 或 5.6 来确认那里的行为是否相同(并且 SQLFiddle.com 出现故障).对原始错误报告的评论(关闭为 not-a-bug)表明 MySQL 5.6可能与 MariaDB 的行为方式相同.

Note: I don't currently have access to a proper MySQL 5.5 or 5.6 to confirm if the behavior is the same there (and SQLFiddle.com is malfunctioning). Comments on the original bug report (closed as not-a-bug) suggest that MySQL 5.6 probably behaves the same way as MariaDB.