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

问题描述 投票:0回答:3

多年来我一直在 MySQL 5.5(或以前的版本)中使用以下查询,没有任何问题:

SELECT t2.Code from (select Country.Code from Country order by Country.Code desc ) AS t2;

结果的顺序总是按照我的需要降序排列。

上周,我刚刚迁移到一个新的 MySQL 版本(实际上,我迁移到了 MariaDB 10.0.14),现在同一个数据库的同一个查询不再按降序排列。它是升序排序的(或使用自然顺序排序,实际上不确定)。

那么,有人可以告诉我这是一个错误还是最新版本的 MySQL/MariaDB 中的行为变化?

mysql sql subquery sql-order-by mariadb
3个回答
37
投票

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

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

ORDER BY

Linux 上的

MariaDB 5.5.39 在没有提供ORDER BY

在子查询中应用
LIMIT
。它 does 但是当给出相应的
LIMIT
时正确应用订单:

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

没有那个

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

记录的行为:

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

“表”(以及

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

您需要将

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

因此 MariaDB 还建议在最外层查询中应用

ORDER BY
,或者在必要时应用
LIMIT

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


4
投票

在较新版本的 MySQL 和 MariaDB 中,您可以通过应用 LIMIT 在子查询中强制使用 ORDER BY。如果不想限制行数,就用最大的BIGINT数作为LIMIT。

这有时可能会派上用场,例如,当需要以所需的顺序生成子查询时,例如应用行号。


0
投票

像这样使用 order + limit 插入子查询:

SELECT * FROM (
  SELECT * 
  FROM some_table 
  ORDER BY date DESC
  LIMIT 0,18446744073709551615
) AS a GROUP BY person
;

It will keep the order before grouping
© www.soinside.com 2019 - 2024. All rights reserved.