例えば、めっちゃでかい学生データベースを扱ってるとするじゃん。苗字だけでソートするのも便利だけど、同じ苗字の学生がいる場合もあるよね。そんなとき、もっと見やすくするために名前でもソートを追加できる。あるいは、注文リストを日付で並べて、そのあと注文合計金額で並べたいとか。こういうときに複数カラムでのソートが役立つんだ。
複数カラムでのソートを使うと: 1. データを決まった順番で並べられる; 2. ソートの優先順位をコントロールできる(まず1つ目のカラム、次に2つ目…); 3. データをもっと構造化して見やすくできる。
複数カラムでのソートの構文
複数カラムでデータをソートしたいときは、おなじみのORDER BYを使うけど、今度はカンマ区切りで複数カラムを並べる。PostgreSQLはまず1つ目のカラムでソートして、同じ値があったら2つ目…って感じでやってくれる。
こんな感じの構文だよ:
SELECT カラムたち
FROM テーブル
ORDER BY カラム1 向き1, カラム2 向き2, ... ;
ここで:
カラム1,カラム2, ... — ソートしたいカラムたち。向き1,向き2, ... — ソートの向き(ASCは昇順、DESCは降順)。- このパラメータは省略できて、デフォルトは
ASCになる。
例1:学生を苗字、次に名前でソート
studentsテーブルに学生データがあるとしよう:
| id | first_name | last_name | age |
|---|---|---|---|
| 1 | Anna | Lin | 20 |
| 2 | Victor | Lin | 22 |
| 3 | Maria | Kim | 21 |
| 4 | Otto | Lin | 23 |
| 5 | Anna | Kim | 20 |
やりたいことは、まず苗字(last_name)、次に名前(first_name)で学生をソートすること。
SELECT id, first_name, last_name, age
FROM students
ORDER BY last_name ASC, first_name ASC;
結果:
| id | first_name | last_name | age |
|---|---|---|---|
| 5 | Anna | Kim | 20 |
| 3 | Maria | Kim | 21 |
| 1 | Anna | Lin | 20 |
| 4 | Otto | Lin | 23 |
| 2 | Victor | Lin | 22 |
見ての通り、まず苗字(Kim、次にLin)で並んでて、その中で名前(Anna、Maria…)で並んでる。リストから人を探したり、出席簿をソートしたいときに超便利!
例2:注文を日付と合計金額でソート
ordersテーブルに注文データがあるとしよう:
| order_id | customer_id | order_date | total |
|---|---|---|---|
| 1 | 101 | 2025-10-01 | 500 |
| 2 | 102 | 2025-10-03 | 200 |
| 3 | 103 | 2025-10-02 | 300 |
| 4 | 104 | 2025-10-01 | 100 |
| 5 | 101 | 2025-10-03 | 600 |
注文をまずorder_dateで、次に注文合計totalを降順でソートしたい。
SQLクエリ:
SELECT order_id, customer_id, order_date, total
FROM orders
ORDER BY order_date ASC, total DESC;
結果:
| order_id | customer_id | order_date | total |
|---|---|---|---|
| 1 | 101 | 2025-10-01 | 500 |
| 4 | 104 | 2025-10-01 | 100 |
| 3 | 103 | 2025-10-02 | 300 |
| 5 | 101 | 2025-10-03 | 600 |
| 2 | 102 | 2025-10-03 | 200 |
見ての通り、同じ日付の注文も合計金額でソートされてる。
NULLのソート:NULLS FIRSTとNULLS LAST
SQLには特別な値NULLがあって、これは「値がない」って意味。詳しい使い方はもうちょい後でやるけど、今はソート時にどう扱うかを紹介するね。
NULLを含むカラムをソートするとき、PostgreSQLは空の値をどこに置くか決める必要がある。
デフォルトでは:
ORDER BY ... ASCのとき:NULLは最後(NULLS LAST)ORDER BY ... DESCのとき:NULLは最初(NULLS FIRST)
この動きが不便なときは、NULLS FIRSTやNULLS LASTで明示的にコントロールできるよ。
構文:
ORDER BY カラム ASC NULLS FIRST
ORDER BY カラム DESC NULLS LAST
例:成績でソート、NULLは「まだ成績ついてない」
SELECT student_id, grade
FROM grades
ORDER BY grade DESC NULLS LAST;
こうすると、まず成績が高い学生、次に低い学生、一番最後にまだ成績がない(NULL)学生が出てくる。
逆に、成績がない学生を最初に表示したい場合
例えば、gradesテーブルで、まだ成績がついてない学生(NULL)がいるとする:
| student_id | grade |
|---|---|
| 101 | NULL |
| 102 | 85 |
| 103 | NULL |
| 104 | 92 |
| 105 | 76 |
まず成績がない学生を表示して、そのあと成績が低い順に並べたい。
SELECT student_id, grade
FROM grades
ORDER BY grade ASC NULLS FIRST;
結果:
| student_id | grade |
|---|---|
| 101 | NULL |
| 103 | NULL |
| 105 | 76 |
| 102 | 85 |
| 104 | 92 |
NULLS FIRSTとORDER BY grade ASCを組み合わせると、NULLのレコードが最初に来て、そのあと成績が昇順で並ぶのを保証できる。
注意点やよくあるミス
初心者がよくやるのは、各カラムのソート向きを書き忘れること。向きを指定しなかったら、PostgreSQLはデフォルトでASCを使うよ。それと、ORDER BYのカラム順が大事ってことも忘れがち。まず1つ目のカラムでソートして、同じ値があったら2つ目…って順番で処理されるからね。
GO TO FULL VERSION