web-dev-qa-db-ja.com

MySQL / MariaDB-サブクエリ内での順序付け

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の動作の変更なのか、誰かに教えてもらえますか?

14
G. Plante

少し掘り下げた後、両方のシナリオを確認できます。

MySQL 5.1は、サブクエリ内にORDER BYを適用します。

Linux上のMariaDB5.5.39は、LIMITが指定されていない場合、サブクエリ内でORDER BYを適用しませんnot。ただし、対応する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が誤動作しています)。 元のバグレポートへのコメント (バグではないとしてクローズ)は、MySQL5.6がおそらくMariaDBと同じように動作することを示唆しています。

26

MySQLとMariaDBの新しいバージョンでは、LIMITを適用することにより、サブクエリでORDERBYを強制できます。行を制限したくない場合は、最大数のBIGINTをLIMITとして使用します。

これは、たとえば行番号を適用する場合など、サブクエリを目的の順序で生成する必要がある場合に便利です。

2
Thalueng