0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

【MySQL】UNIONするとソートが効かなくなる

Last updated at Posted at 2024-07-09

やりたいこと

2つのテーブルから条件に合うデータを抽出し、それぞれID順にソートしてから結合する。

dogsテーブルとcatsテーブルから、5歳未満のレコードを抽出し、それぞれID順にソートしてから結合する。

  • dogsテーブル
id name age
1 ムギ 9
2 ココ 3
3 ソラ 8
4 モカ 2
  • catsテーブル
id name age
1 レオ 6
2 ルナ 1
3 ベル 7
4 キナコ 4
  • 期待する結合結果
id name age
2 ココ 3
4 モカ 2
2 ルナ 1
4 キナコ 4

NGな書き方

(SELECT * FROM dogs WHERE age < 5 ORDER BY id)
UNION
(SELECT * FROM cats WHERE age < 5 ORDER BY id);

結合結果

id name age
4 モカ 2
2 ココ 3
2 ルナ 1
4 キナコ 4

dogsテーブルがID順にならなかった。
(設定しているINDEXが原因だと予想しているが、)ソートが効いていない。

ドキュメントを見てみる

個々の SELECT ステートメントに ORDER BY を使用すると、UNION では順序付けられていない行のセットがデフォルトで生成されるため、最終結果に行が表示される順序については何も意味しません。 したがって、このコンテキストの ORDER BY は通常、SELECT 用に取得する選択済の行のサブセットを決定するために LIMIT とともに使用されますが、最終的な UNION 結果の行の順序には必ずしも影響しません。 SELECT に LIMIT がない状態で ORDER BY が表示された場合は、どのような場合にも効果がないため最適化されます。

ORDER BY は LIMIT と一緒に使わないと無視される

OKな書き方

LIMIT を設定することで期待した結果が得られた(が、微妙)。

(SELECT * FROM dogs WHERE age < 5 ORDER BY id LIMIT 10)
UNION
(SELECT * FROM cats WHERE age < 5 ORDER BY id LIMIT 10);

結合結果

id name age
2 ココ 3
4 モカ 2
2 ルナ 1
4 キナコ 4

採用した書き方

LIMIT を設定したくなかったので、他の書き方を採用した。

(SELECT 1 as sort, * FROM dogs WHERE age < 5)
UNION
(SELECT 2 as sort, * FROM cats WHERE age < 5)
ORDER BY sort, id;

結合結果

sort id name age
1 2 ココ 3
1 4 モカ 2
2 2 ルナ 1
2 4 キナコ 4

不要なカラムは後続処理で消した:innocent:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?