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 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と同じように動作することを示唆しています。
MySQLとMariaDBの新しいバージョンでは、LIMITを適用することにより、サブクエリでORDERBYを強制できます。行を制限したくない場合は、最大数のBIGINTをLIMITとして使用します。
これは、たとえば行番号を適用する場合など、サブクエリを目的の順序で生成する必要がある場合に便利です。