SQLでソート順を指定するorder by句。当記事では、order byを使ったサンプルコードを紹介しています。
以下、データベースとして、MySQLのサンプルデータベースEmployeesを使っています。SQL実行結果の表示にはphpMyAdminを使用しています。
SQLのorder byの基本的な使い方
SELECT カラム名 FROM テーブル名 ORDER BY ソートするカラム名 [ASC / DESC]
order byはselect文と組み合わせることが多いですが、update文やdelete文にも使えます。
SELECT * FROM `employees` order by birth_date desc
上記のSQLは、employees(社員テーブル)から、birth_date(誕生日)を降順にデータを取得します。
結果はこうなります。
※1965年2月1日生まれが、社員の中で最も若いデータ
order byのサンプルコード
複数カラムを昇順・降順混ぜてソートするサンプル
order byの指定には、複数カラムの指定が可能です。また、カラムごとに別々にDESC(降順)、ASC(昇順)の指定ができます。
降順・昇順を指定しない場合はデフォルト(昇順)になります。
SELECT * FROM `employees` ORDER BY emp_no DESC, first_name, hire_date ASC
上記のSQLは、employees(社員テーブル)から、emp_no(社員番号)降順、first_name(姓名の名)昇順、last_name(姓名の姓)昇順でデータを取得します。ASC、DESCの指定を省略したfirst_nameのソートはASC(昇順)になります。
実行結果はこうなります。
order byに条件を指定する例サンプルコード
order byのカラム指定に条件を指定することが可能です。
SELECT * FROM `employees` ORDER BY emp_no=20000 DESC, first_name, hire_date ASC
上記SQLは、employees(社員テーブル)から、emp_no(社員番号)が20000ものを一番最初に(それ以外は不定)、first_name(姓名の名)を昇順、hire_date(雇用日)を昇順で取得します。
実行すると、こうなります。
emp_no(社員番号)20000のデータが先頭に来ているのは良いのですが、それ以降はemp_noがバラバラです。
内部的には、ソートの第一条件「emp_no=20000とそれ以外」、第二条件「first_nameを昇順で」、第三条件「hire_dateを昇順で」ということになります。
「emp_no=20000のデータを先頭に、それ以外を降順に」というソート指定をするには、case式を組み合わせます。
case式を組み合わせて任意の順番でソートする例
SELECT * FROM `employees` ORDER BY case emp_no WHEN 20000 THEN 1 ELSE 2 END, emp_no DESC, first_name ASC
上記SQLは、employees(社員テーブル)から、emp_no=20000とそれ以外を昇順、emp_no(社員番号)を降順、first_name(姓名の名)を昇順にデータを取得します。
実行結果はこうなります。
「case emp_no WHEN 20000 THEN 1 ELSE 2 END」というcase式で、ソートの第一条件が「1」(emp_no=20000)または「2」(emp_noが20000以外)の昇順になるんですね。
ソート第二条件の「emo_no DESC」が適用された時点でソート順位が確定するため、ソート第三条件のfirst_name ASCは意味がないことになります。
【関連記事】
▶SQLのCASE式サンプル集 order byやgroup byとの組み合わせもバッチリ
fieldを使って任意の順番でソート指定する
MySQLのみの関数ですが、field指定を使って任意の順番でソートが可能です。
SELECT * FROM `departments` where dept_name in ('Marketing','Sales','Development') order by field( dept_name, 'Marketing','Sales', 'Development')
departmens(部署テーブル)のうち、dept_name(部署名)がMarketing、Sales、Developmentのものを取得し、Marketing、Sales、Developmentの順にソートして取得します。
結果はこうなります。
order by 1って何? 列番号でソート順を指定する
order by指定には、カラム名以外に列番号を指定可能です。order by 1は、第一列のカラムを昇順にソートする指定なんですね。
SELECT * FROM `employees` ORDER BY 2,6 DESC,1 ASC
上記SQLは、employees(社員テーブル)から、列2(birth_date 誕生日)昇順、列6(hire_date 雇用日)降順、列1(emp_no 社員番号)昇順でデータを取得します。
実行するとこうなります。
列番号でのソート指定は、SQL標準の観点から見ると、あまり好ましくありません。
NULLのソート順を決める
Oracle限定ですが、ソート対象のカラムがNULLだったときの扱いを指定する方法があります。
「NULL_FIRST」でNULLのカラムは先頭に、「NULL_LAST」で、NULLのカラムは最後尾になります。
SELECT * FROM `employees` ORDER BY hire_date NULL_FIRST DESC, NULL_LAST first_name
上記のSQLは、hire_date(雇用日)がNULLのものを先頭にして降順に、first_name(姓名の名)がNULLのものを最後尾にして昇順にソートする指定になります。
order byを使うときの注意点
order byでユニークカラム以外を指定するとlimitで重複が出る
DBMSの種類やバージョンによっては、order byでソート指定したカラムがユニークではない場合、並びが不定になるケースがあるようです。
SELECT * FROM `employees` order by hire_date limit 10
上記SQLは、employees(社員テーブル)から、hire_date(雇用日)を昇順にソートして10件取得します。
結果はこうなりました。
MySQL 5.7では、何度クエリを実行しても、ソート順は固定のままでした。
ユニークでないカラムをソート指定した場合には、並び順は保証されないケースがあることは覚えておきましょう。
参考)ORDER BYとLIMIT, OFFSETの組み合わせには注意しよう | MMMブログ
order byが効かない group byの実行順序に注意
まとめ
- order byでは、複数カラムに昇順・降順の混合指定が可能
- order byに条件指定したデータを先頭に並べることができる
- 任意の順番でソートするには、order byにcase式を組み合わせる
- MySQLでは、field関数を使って任意の順番にソートが可能
- order by 1などの列番号指定は、なるべく避ける
- Oracleでは、ソートでのNULLのカラムの扱いを指定可能
- DBMSのシュルいやバージョンにより、ユニークでないカラムをソート指定すると並び順が不定になるケースあり