コマンド道場

ORDER BY 句の使い方

行は減らない。並びだけが変わる

shain社員

namesalary
鈴木980000
佐藤720000
田中520000
中村530000
小林445050
加藤610000

ORDER BY salary DESC並べ替えた結果

namesalary
鈴木980000
佐藤720000
山田700000
清水650000
加藤610000
中村530000

ORDER BY salary DESC

  • 行は 1 つも減りません。並び順だけが変わります(左右で同じ 18 行)

並べ替えは行を捨てません。左右で行数は同じです。行を減らすのは WHERE や LIMIT の仕事です。

ORDER BY結果の並び順を決めます。いちばん大事な事実は、指定しなければ順番は保証されないということです。たまたま並んで見えても、それは偶然です。並びに意味があるなら必ず書いてください。

主要 7 製品で通用 そのまま使える: PostgreSQL / MySQL / MariaDB / SQLite / SQL Server / Oracle Database / IBM Db2

製品ごとの対応表(実測)を見る

このページの実行結果と図は、すべて本物のデータベースに同じ SQL を流して得たものです。手で書いた「たぶんこうなる」ではありません。

01⚠️ 指定しなければ順番は保証されない

結論: `ORDER BY` が無い問い合わせの並び順は、決まっていません。

小さい表では登録順に見えることが多く、それで動いているように錯覚します。しかし表が大きくなったり、索引が使われたり、処理が並列化されると順番は変わります。

「たまたま並んでいた」ものに依存した処理は、いつか必ず壊れます。 並びに意味があるなら必ず ORDER BY を書いてください。

1 行ずつ、何をしているか
  1. SELECT name, salary何を出すか
  2. FROM shainどの表を見るか
  3. WHERE taishoku_on IS NULLどの行を残すか
  4. ORDER BY salary DESC,第 1 キー(高い順)
  5. shain_id第 2 キー(同額のときの決着)

ORDER BY は最後に効きます。だから SELECT で付けた別名も使えます。

並び順を指定しない
SELECT name, salary FROM shain;
namesalary
鈴木980000
佐藤720000
田中520000
中村530000
小林445050

18 … うち先頭 5 行を表示

この環境では登録順に見えますが、これは保証された動きではありません。

給与の高い順に並べる
SELECT name, salary FROM shain ORDER BY salary DESC;
namesalary
鈴木980000
佐藤720000
山田700000
清水650000
加藤610000

18 … うち先頭 5 行を表示

DESC で降順です。省略すると昇順(ASC)になります。

02同じ値のときをどう決めるか

結論: 第 1 キーが同じ行の並びは、第 2 キーを書かないと決まりません。

この表には給与が同額の社員が 2 人います。ORDER BY salary DESC だけでは、その 2 人のどちらが先に来るかが決まっていません。

ページ送り(`LIMIT` と `OFFSET`)を使うときは特に危険です。 順番が実行のたびに変われば、同じ行が 2 度出たり、逆に抜け落ちたりします。一意な列を最後のキーに足しておくと安全です。

同額の社員が 2 人いる
SELECT name, salary FROM shain WHERE salary = 530000 ORDER BY salary DESC;
namesalary
中村530000
伊藤530000

2

この 2 人の順番は、第 1 キーだけでは決まりません。

一意な列を第 2 キーに足す
SELECT shain_id, name, salary FROM shain ORDER BY salary DESC, shain_id;
shain_idnamesalary
1鈴木980000
2佐藤720000
8山田700000
14清水650000
6加藤610000
4中村530000
10伊藤530000
3田中520000

18 … うち先頭 8 行を表示

shain_id は一意なので、これで並びが 1 通りに決まります。何度実行しても同じ順番です。

03式や別名でも並べられる

結論: `ORDER BY` には列名だけでなく、式も `SELECT` で付けた別名も書けます。

ORDER BYSELECT のあとに評価されるため、そこで作った名前をそのまま使えます(WHERE では使えません)。

CASE を書けば、文字コード順とは関係のない業務上の並びも作れます。ステータスの重要度順などはこの形で表現します。

別名で並べ替える
SELECT name, salary * 12 AS nenshu FROM shain ORDER BY nenshu DESC, name LIMIT 5;
namenenshu
鈴木11760000
佐藤8640000
山田8400000
清水7800000
加藤7320000

5

SELECT で付けた nenshu を、そのまま並べ替えのキーにできます。

⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表

式で並べ替える
SELECT name, hired_on FROM shain ORDER BY EXTRACT(YEAR FROM hired_on), name LIMIT 6;
namehired_on
清水2013-04-01
鈴木2014-04-01
山田2015-04-01
佐藤2016-10-01
山本2016-04-01
伊藤2017-04-01

6

並べ替えのキーに使った式は、結果に出さなくても構いません。

⚠️ この書き方は SQLite / SQL Server / Oracle Database / IBM Db2 では使えません(EXTRACT(日付の一部を取り出す))。製品ごとの対応表

04⚠️ 文字列の並び順は「照合順序」で決まる

結論: 文字列の大小は、その列の照合順序(collation)が決めます。

数値や日付は誰が見ても大小が同じですが、文字列は違います。大文字と小文字をどう扱うか、記号や空白をどう並べるかは、照合順序の設定で変わります。

日本語では特に注意が要ります。多くの環境で、漢字は「読み」ではなく文字コード順に並びます。「五十音順に並べたい」なら、読み仮名の列を別に持って、そちらで並べるのが確実です。

同じ SQL でも、環境の照合順序が違えば並び順が変わります。エラーにならない差なので、並びに意味があるなら、どの照合順序で動いているかを確かめてください。

氏名で並べてみる
SELECT name FROM shain ORDER BY name;
name
中村
井上
伊藤
佐藤
加藤
吉田
大野
小林

18 … うち先頭 8 行を表示

五十音順ではなく文字コード順に並んでいます。日本語を「読み」で並べたいなら、読みを別の列に持つ必要があります。

部署名でも同じ
SELECT busho_name FROM busho ORDER BY busho_name;
busho_name
マーケ
営業
基盤
法務
管理
経営
開発

7

並んではいますが、この順序に業務上の意味はありません。意味のある順に並べたいなら、CASE で明示するか並び順の列を持ちます。

05⚠️ NULL をどこに置くかは製品で違う

結論: NULL の位置は SQL の規格では決まっておらず、製品ごとの既定に従います。

PostgreSQL は昇順で最後・降順で最初、MySQL は逆に昇順で最初に来ます。同じ SQL が製品によって違う順番を返す、というエラーにならない差です。

位置に意味があるなら NULLS FIRST / NULLS LAST で明示してください。⚠️ ただしこの書き方は MySQL・MariaDB・SQL Server にはありません。それらでは並べ替えのキーに 列 IS NULL を足して代用します。

既定では NULL がどこに来るか
SELECT name, busho_id FROM shain ORDER BY busho_id;
namebusho_id
鈴木1
佐藤2
田中2
中村2
小林2
山田3

18 … うち先頭 6 行を表示

PostgreSQL では昇順のとき NULL が最後に来ます。他の製品では違うことがあります。

NULL を先頭に置く
SELECT name, busho_id FROM shain ORDER BY busho_id NULLS FIRST, shain_id;
namebusho_id
渡辺NULL
大野NULL
鈴木1
佐藤2
田中2

18 … うち先頭 5 行を表示

位置を明示すれば、既定に頼らずに済みます。部署未定の社員が先頭に来ました。

⚠️ この書き方は MySQL / MariaDB / SQL Server では使えません(ORDER BY ... NULLS LAST)。製品ごとの対応表

NULLS LAST が無い製品での代用
SELECT name, busho_id FROM shain ORDER BY (busho_id IS NULL), busho_id, shain_id;
namebusho_id
鈴木1
佐藤2
田中2
中村2
小林2

18 … うち先頭 5 行を表示

IS NULL は真のとき大きい値として扱われるので、これで NULL が最後に来ます。どの製品でも通る書き方です。

自分で打ってみる

このページの例と同じデータが入った本物のデータベースを、この場(あなたのブラウザの中)で起動できます。打った SQL がサーバーへ送られることはありません。

押すと初回だけ約 9MB を読み込みます(2 回目以降はキャッシュされます)。

解いてみる

読んだだけでは書けるようになりません。実行結果で採点します。

関連するトピック

  • LIMIT / FETCH FIRST件数を絞るときは、並び順が決まっていないと結果が安定しません。
  • SELECT 句ORDER BY は SELECT のあとに評価されるので、別名が使えます。
  • IS NULLNULL の位置を自分で決めるときに使います。

根拠(一次情報)