順番に読み進めながら学べます

DISTINCT・ORDER BY・LIMIT — 結果セットを整える

SQL の DISTINCT・ORDER BY・LIMIT・OFFSET を解説します。重複除去、並び替え、件数制限、OFFSET によるページングまで、CSV の成績データを使ってブラウザで実行しながら学べます。

本記事で使うデータ — CSV から読み込んだ score テーブル

本記事では CSV ファイルから自動ロードされた `score` テーブル を題材に、SELECT の結果を整える 4 つの構文 — DISTINCT(重複除去)、ORDER BY(並び替え)、LIMIT(件数制限)、OFFSET(先頭スキップ)— を順に学びます。

score テーブルは id / name / subject / score / recorded_on の 5 列を持ち、5 名の受験者(Alice / Bob / Carol / Dave / Eve)が Math / English / Science の 3 科目を受験した、計 15 行のデータです。

演習に入る前に、score テーブルの 列定義データのサンプル を確認しておきます。

PRAGMA table_info(score); で列名・型・主キーを確認してください。

SELECT * FROM score LIMIT 5; で先頭 5 行のデータをプレビューしてください。

SQL エディタ

クエリを実行してください

DISTINCT — 重複行を除いて取り出す

SELECT の結果に 同じ値の行が複数回 含まれることがあります。たとえば score テーブルから name 列だけを取り出すと、Alice / Bob / Carol / Dave / Eve の 5 名がそれぞれ 3 科目分、計 15 行返ります。

`SELECT DISTINCT 列, ...` の形に書くと、結果セットの中で 重複している行をまとめて 1 行に圧縮 できます。複数列を指定した場合は「列の組み合わせ」が同じ行を重複と見なします。

DISTINCT の動き
SELECT name FROM score;SELECT DISTINCT name FROM score;AliceAliceAliceBobAliceCarolBobDaveBob ...Eve計 15 行 (重複あり)計 5 行 (重複除去後)
DISTINCT を付けない SELECT は重複した行をそのまま返し、DISTINCT を付けると同じ値の行は 1 つにまとまります。
-- 受験者の名前を重複なく一覧で取り出す
SELECT DISTINCT name FROM score;

-- 受験した科目を重複なく一覧で取り出す
SELECT DISTINCT subject FROM score;

-- 「名前と科目」の組み合わせで重複除去(= 全 15 行が一意)
SELECT DISTINCT name, subject FROM score;

DISTINCT を付けたときと付けないときで、結果が どう変わるか を 1 つのコンソールで並べて確認します。(正しく実行できれば解説が表示されます)

score テーブルから、`DISTINCT` を付けずに name 列を取り出してください。

② 同じコンソールに続けて、`DISTINCT` を付けて name 列を取り出してください。

③ 1 つ目は 15 行(同じ名前が 3 回ずつ)、2 つ目は 5 行(重複が 1 行に圧縮)になることを確認してください。

SQL エディタ

クエリを実行してください

ORDER BY — 結果を並び替える

SQL は 行の順序を保証しない のが基本仕様で、SELECT * FROM score; のように書いてもどの順番で行が返るかは DB の実装に任されます。結果を意図通りの順序で並べたいときは `ORDER BY 列 [ASC|DESC]` を付けます。

- ASC(昇順 / 小 → 大)が既定値で、省略可

- DESC(降順 / 大 → 小)は明示的に書く

- カンマ区切りで 複数列 を指定すると、第 1 列が同じ行は第 2 列で並べる、という多段ソートになります

ORDER BY の昇順 と 降順
元データ(順不同)ORDER BY score(ASC = 昇順)ORDER BY score DESC(降順)Alice 92Dave 65Carol 95Bob 76Bob 76Alice 92Carol 95Eve 87Eve 87Dave 65Alice 92Bob 76Eve 87Carol 95Dave 65
ORDER BY を付けない場合は順序が保証されませんが、ASC / DESC を指定すると意図通りの並びになります。デフォルトは ASC(昇順)です。
-- 1) 1 列で昇順(ASC は省略可)
SELECT name, score FROM score ORDER BY score;

-- 2) 1 列で降順
SELECT name, score FROM score ORDER BY score DESC;

-- 3) 複数列で並び替え(科目順 → 同科目内は点数の高い順)
SELECT name, subject, score FROM score ORDER BY subject ASC, score DESC;

ORDER BY の細かい仕様

- ORDER BYWHERE のあと、LIMIT の前に置くのが正しい順序です。SELECT 列 FROM 表 WHERE 条件 ORDER BY 列 DESC LIMIT N; の並びを覚えておくと迷いません。

- ORDER BY の右辺には 列番号ORDER BY 2 DESC で SELECT した 2 つ目の列で並べる)も書けますが、可読性が落ちるので 列名で書く のが主流です。

- 文字列の並び順は本講座のコンソールでは大文字 → 小文字の順(ASCII 順)になります。DB によっては 'A''a' を同等に扱う場合もあります。

成績一覧画面で「受験者を名前順に並べ、各受験者の中では点数の低い科目から表示したい」という要件を想定します。

score テーブルから namesubjectscore の 3 列を取り出してください。

`name` 列の昇順、同じ名前の中では `score` 列の昇順 で並べ替えてください。

③ 結果が 15 行になり、先頭が Alice Science 78、最後が Eve English 93 になっていることを確認してください。

SQL エディタ

クエリを実行してください

実践 2 と同じ名前順のままで、各受験者の中では 得点の高い科目を上に 表示する画面を想定します。

score テーブルから namesubjectscore の 3 列を取り出してください。

`name` 列の昇順、同じ名前の中では `score` 列の降順 で並べ替えてください。

③ 結果が 15 行になり、先頭が Alice Math 92、最後が Eve Science 86 になっていることを確認してください。

SQL エディタ

クエリを実行してください

LIMIT と OFFSET — 件数を絞ってページングする

結果セットが 100 行・1 万行と大きくなると、画面に全部出すと重くなり、ユーザーも見切れません。`LIMIT N` を付けると 先頭から N 行だけ を取り出せます。これに `OFFSET M` を組み合わせると、先頭 M 行を読み飛ばしてから N 行 を取り出せるので、「6〜10 件目」「11〜20 件目」のように ページング ができます。

LIMIT と OFFSET によるページング
ORDER BY 後(全 7 行)LIMIT 3(1 ページ目)LIMIT 3 OFFSET 3(2 ページ目)1 位 Carol 95取得スキップ2 位 Eve 93取得スキップ3 位 Alice 92取得スキップ4 位 Bob 90取得5 位 Bob 88取得6 位 Eve 87取得7 位 Eve 86
ORDER BY で並べた結果に対して、LIMIT が「何件取るか」、OFFSET が「先頭から何件スキップするか」を決めます。OFFSET = (ページ番号 - 1) × 1 ページの件数 が基本式です。
-- 1) 上位 5 件を取り出す(ランキング TOP 5)
SELECT name, subject, score FROM score
ORDER BY score DESC
LIMIT 5;

-- 2) 6 件目〜10 件目を取り出す(2 ページ目)
SELECT name, subject, score FROM score
ORDER BY score DESC
LIMIT 5 OFFSET 5;

-- 3) ページング式: ページ N、1 ページ K 件
--    LIMIT K OFFSET (N - 1) * K
--    例: 3 ページ目、1 ページ 5 件 → LIMIT 5 OFFSET 10
ページ1 ページの件数OFFSETLIMIT対象順位
15051〜5 位
25556〜10 位
3510511〜15 位
1100101〜10 位
210101011〜20 位
1200201〜20 位

ORDER BY なしの LIMIT は順序が保証されない

SELECT * FROM score LIMIT 5; のように `ORDER BY` を省いて `LIMIT` だけを書くと、どの 5 行が返るかは DB の実装に任されます。SQLite のように挿入順で返ることが多い DB でも、SQL の規格上は順序は不定です。MySQL / PostgreSQL ではインデックスや実行計画の都合で別の行が返ることがあります。

ランキング・ページング・「先頭 N 件」のような順序が意味を持つ取得には、必ず `ORDER BY` を付けてから `LIMIT` を書きます

成績ダッシュボードに「全教科を通したトップ 5」を載せたい、という要件を想定します。

score テーブルから namesubjectscore の 3 列を取り出してください。

`score` 列の降順 で並べ、先頭から 5 行だけ に絞り込んでください。

③ 結果が 5 行になり、1 行目が Carol Math 95、5 行目が Bob English 88 になっていることを確認してください。

SQL エディタ

クエリを実行してください

ダッシュボードに「もっと見る」を押すとトップ 5 の 次の 5 件 を表示する、というページング機能を想定します。

① 実践 4 と同じ並び順(score 降順)で、namesubjectscore の 3 列を取り出してください。

先頭の 5 行をスキップして 次の 5 行(6 位〜10 位)を取り出してください。

③ 結果が 5 行になり、先頭が Eve Math 87、最後が Alice Science 78 になっていることを確認してください。

SQL エディタ

クエリを実行してください
QUIZ

理解度チェック

まずは1問ずつ答えてみましょう。

Q1次のうち、SELECT DISTINCT の説明として正しいものはどれですか。

Q2SELECT name, score FROM score ORDER BY score DESC; の結果として正しいものはどれですか。

Q3SELECT * FROM score ORDER BY score DESC LIMIT 5 OFFSET 10; を実行したときに返る行として正しいものはどれですか。