【SQL】ORDER BY:検索結果を並び替える

  • #SQL
ORDER BY句 並び順
DESC 降順 高い(大きい)順に並べる
ASC 昇順 低い(小さい)順に並べる
  • ORDER BY句は、いつどんなときでもSELECT文の最後に書く
    → 行の並び替え(ソート)は結果を返す直前に行うため
  • ORDER BY句に続く列名をソートキーと呼ぶ

降順、昇順に並び替える

並び替えの基準となる列名:hanbai_tanka(ソートキー)

/* ASC */
SELECT shohin_id, shohin_mei, hanbai_tanka, shiire_tanka
FROM Shohin
ORDER BY hanbai_tanka ASC;

/* hanbai_tankaが昇順に並ぶ */
 shohin_id |   shohin_mei   | hanbai_tanka | shiire_tanka 
-----------+----------------+--------------+--------------
 0008      | ボールペン     |          100 |             
 0006      | フォーク       |          500 |             
 0002      | 穴あけパンチ   |          500 |          320
 0007      | おろしがね     |          880 |          790
 0001      | Tシャツ        |         1000 |          500
 0004      | 包丁           |         3000 |         2800
 0003      | カッターシャツ |         4000 |         2800
 0005      | 圧力鍋         |         6800 |         5000

/* DESC */
SELECT shohin_id, shohin_mei, hanbai_tanka, shiire_tanka
FROM Shohin
ORDER BY hanbai_tanka DESC;

/* hanbai_tankaが降順に並ぶ */
 shohin_id |   shohin_mei   | hanbai_tanka | shiire_tanka 
-----------+----------------+--------------+--------------
 0005      | 圧力鍋         |         6800 |         5000
 0003      | カッターシャツ |         4000 |         2800
 0004      | 包丁           |         3000 |         2800
 0001      | Tシャツ        |         1000 |          500
 0007      | おろしがね     |          880 |          790
 0002      | 穴あけパンチ   |          500 |          320
 0006      | フォーク       |          500 |             
 0008      | ボールペン     |          100 |             

ASC、DESCの記述を省略した場合:昇順に並び替えられる

/* 記述を省略 */
SELECT shohin_id, shohin_mei, hanbai_tanka, shiire_tanka
FROM Shohin
ORDER BY hanbai_tanka;

/* hanbai_tankaが昇順に並ぶ */
 shohin_id |   shohin_mei   | hanbai_tanka | shiire_tanka 
-----------+----------------+--------------+--------------
 0008      | ボールペン     |          100 |             
 0006      | フォーク       |          500 |             
 0002      | 穴あけパンチ   |          500 |          320
 0007      | おろしがね     |          880 |          790
 0001      | Tシャツ        |         1000 |          500
 0004      | 包丁           |         3000 |         2800
 0003      | カッターシャツ |         4000 |         2800
 0005      | 圧力鍋         |         6800 |         5000

複数のソートキーを指定する

ソートキー:hanbai_tanka, shohin_id

/* ASC */
SELECT shohin_id, shohin_mei, hanbai_tanka, shiire_tanka
FROM Shohin
ORDER BY hanbai_tanka, shohin_id ASC;

 shohin_id |   shohin_mei   | hanbai_tanka | shiire_tanka 
-----------+----------------+--------------+--------------
 0008      | ボールペン     |          100 |             
 0002      | 穴あけパンチ   |          500 |          320 --値段が同じだと商品IDの昇順
 0006      | フォーク       |          500 |             
 0007      | おろしがね     |          880 |          790
 0001      | Tシャツ        |         1000 |          500
 0004      | 包丁           |         3000 |         2800
 0003      | カッターシャツ |         4000 |         2800
 0005      | 圧力鍋         |         6800 |         5000
/* DESC */
SELECT shohin_id, shohin_mei, hanbai_tanka, shiire_tanka
FROM Shohin
ORDER BY hanbai_tanka, shohin_id DESC;

 shohin_id |   shohin_mei   | hanbai_tanka | shiire_tanka 
-----------+----------------+--------------+--------------
 0008      | ボールペン     |          100 |             
 0006      | フォーク       |          500 |             --値段が同じだと商品IDの降順
 0002      | 穴あけパンチ   |          500 |          320 
 0007      | おろしがね     |          880 |          790
 0001      | Tシャツ        |         1000 |          500
 0004      | 包丁           |         3000 |         2800
 0003      | カッターシャツ |         4000 |         2800
 0005      | 圧力鍋         |         6800 |         5000

ORDER BY句に複数のソートキーを指定した場合、指定した順に優先される。


降順と昇順を列ごとに指定する

例①

  1. hanbai_tankaを昇順で並び替え
  2. shohin_idを降順で並び替え
SELECT shohin_id, shohin_mei, hanbai_tanka, shiire_tanka
FROM Shohin
ORDER BY hanbai_tanka ASC, shohin_id DESC;

/* 販売単価は昇順に並んでいる
  販売単価が同じとき、商品IDは降順で並んでいる */

 shohin_id |   shohin_mei   | hanbai_tanka | shiire_tanka 
-----------+----------------+--------------+--------------
 0008      | ボールペン     |          100 |             
 0006      | フォーク       |          500 |             --商品ID:0006
 0002      | 穴あけパンチ   |          500 |          320 --商品ID:0002
 0007      | おろしがね     |          880 |          790
 0001      | Tシャツ        |         1000 |          500
 0004      | 包丁           |         3000 |         2800
 0003      | カッターシャツ |         4000 |         2800
 0005      | 圧力鍋         |         6800 |         5000

例②

  1. hanbai_tankaを降順で並び替え
  2. shohin_idを昇順で並び替え
SELECT shohin_id, shohin_mei, hanbai_tanka, shiire_tanka
FROM Shohin
ORDER BY hanbai_tanka DESC, shohin_id ASC;

/* 販売単価は降順に並んでいる
  販売単価が同じとき、商品IDは昇順で並んでいる */

 shohin_id |   shohin_mei   | hanbai_tanka | shiire_tanka 
-----------+----------------+--------------+--------------
 0005      | 圧力鍋         |         6800 |         5000
 0003      | カッターシャツ |         4000 |         2800
 0004      | 包丁           |         3000 |         2800
 0001      | Tシャツ        |         1000 |          500
 0007      | おろしがね     |          880 |          790
 0002      | 穴あけパンチ   |          500 |          320  --商品ID:0002
 0006      | フォーク       |          500 |               --商品ID:0006
 0008      | ボールペン     |          100 |             

NULLの順番はどうなる?

【検証】NULLの存在している列をソートキーに指定する

ソートキー:shiire_tanka

/* ASC */
SELECT shohin_id, shohin_mei, hanbai_tanka, shiire_tanka
FROM Shohin
ORDER BY shiire_tanka ASC;

 shohin_id |   shohin_mei   | hanbai_tanka | shiire_tanka 
-----------+----------------+--------------+--------------
 0002      | 穴あけパンチ   |          500 |          320
 0001      | Tシャツ        |         1000 |          500
 0007      | おろしがね     |          880 |          790
 0003      | カッターシャツ |         4000 |         2800
 0004      | 包丁           |         3000 |         2800
 0005      | 圧力鍋         |         6800 |         5000
 0006      | フォーク       |          500 |              -- NULL
 0008      | ボールペン     |          100 |              -- NULL

/* DESC */
SELECT shohin_id, shohin_mei, hanbai_tanka, shiire_tanka
FROM Shohin
ORDER BY shiire_tanka DESC;

 shohin_id |   shohin_mei   | hanbai_tanka | shiire_tanka 
-----------+----------------+--------------+--------------
 0006      | フォーク       |          500 |              -- NULL
 0008      | ボールペン     |          100 |              -- NULL
 0005      | 圧力鍋         |         6800 |         5000
 0004      | 包丁           |         3000 |         2800
 0003      | カッターシャツ |         4000 |         2800
 0007      | おろしがね     |          880 |          790
 0001      | Tシャツ        |         1000 |          500
 0002      | 穴あけパンチ   |          500 |          320

【結論】ソートキーにNULLが含まれていた場合、先頭か末尾にまとめられる


ソートキーに別名は指定できる?

GROUP BY句では集約キーに別名は指定できなかった (指定して正常に動くケースもあるけど、事故の元なので使わないのが◎ 関連:【SQL】GROUP BY:グループに切り分ける)

ソートキーには別名は使えるのか??


【検証】ソートキーに別名をつける

/* ASC */
SELECT shohin_id AS id, hanbai_tanka AS "販売単価"
FROM Shohin
ORDER BY 販売単価, id ASC;

/* 正しく昇順に並べられている */
  id  | 販売単価 
------+----------
 0008 |      100
 0002 |      500
 0006 |      500
 0007 |      880
 0001 |     1000
 0004 |     3000
 0003 |     4000
 0005 |     6800
/* DESC */
SELECT shohin_id AS id, hanbai_tanka AS "販売単価"
FROM Shohin
ORDER BY 販売単価, id DESC;

/* 正しく降順に並べられている */
  id  | 販売単価 
------+----------
 0008 |      100
 0006 |      500
 0002 |      500
 0007 |      880
 0001 |     1000
 0004 |     3000
 0003 |     4000
 0005 |     6800

【結論】ORDER BY句では、SELECT句でつけた別名を指定できる


GROUP BY句では使えないのに、ORDER BY句では使える。 理由は実行順序↓(ざっくり)

FROM → WHERE → GROUP BY → HAVING → SELECT(ここで別名をつける) → ORDER BY

  • GROUP BY句が実行されるとき、SELECT句でつけられている別名を認識できない
  • ORDER BY句はSELECT句の後に実行されるので、別名を認識できる

SELECT句に含まれていない列も指定できる

ソートキー:shohin_id

/* ソートキーがSELECT句に含まれている */
SELECT shohin_id, shohin_mei, hanbai_tanka, shiire_tanka
FROM Shohin
ORDER BY shohin_id DESC;

/* shohin_idが降順に並んでいる */
 shohin_id |   shohin_mei   | hanbai_tanka | shiire_tanka 
-----------+----------------+--------------+--------------
 0008      | ボールペン     |          100 |             
 0007      | おろしがね     |          880 |          790
 0006      | フォーク       |          500 |             
 0005      | 圧力鍋         |         6800 |         5000
 0004      | 包丁           |         3000 |         2800
 0003      | カッターシャツ |         4000 |         2800
 0002      | 穴あけパンチ   |          500 |          320
 0001      | Tシャツ        |         1000 |          500
/* ソートキーがSELECT句に含まれていない */
SELECT shohin_mei, hanbai_tanka, shiire_tanka
FROM Shohin
ORDER BY shohin_id DESC;

/* 含んでいるときと、並び順が一致している */
   shohin_mei   | hanbai_tanka | shiire_tanka 
----------------+--------------+--------------
 ボールペン     |          100 |             
 おろしがね     |          880 |          790
 フォーク       |          500 |             
 圧力鍋         |         6800 |         5000
 包丁           |         3000 |         2800
 カッターシャツ |         4000 |         2800
 穴あけパンチ   |          500 |          320
 Tシャツ        |         1000 |          500

テーブルに存在している列であれば、ソートキーに指定できる


集約関数も指定できる

ソートキー:COUNT(*)

SELECT shohin_bunrui, COUNT(*)
FROM Shohin
GROUP BY shohin_bunrui
ORDER BY COUNT(*) ASC;

/* countが昇順に並んでいる */
 shohin_bunrui | count 
---------------+-------
 衣服          |     2
 事務用品      |     2
 キッチン用品  |     4
SELECT shohin_bunrui, COUNT(*)
FROM Shohin
GROUP BY shohin_bunrui
ORDER BY COUNT(*) DESC;

/* countが降順に並んでいる */
 shohin_bunrui | count 
---------------+-------
 キッチン用品  |     4
 衣服          |     2
 事務用品      |     2

関連記事:【SQL】ORDER BY:列番号を使わない

参考書籍:ミック『SQL 第2版 ゼロからはじめるデータベース操作』(翔泳社)