Q1次のうち、SELECT DISTINCTの説明として正しいものはどれですか。
DISTINCT・ORDER BY・LIMIT — 結果セットを整える
この記事は、基礎から複雑なSQL,SQLチューニングまでSQLの実践的なスキルを1からマスターする「SQL入門講座の一部」です。
DISTINCTで重複除去、ORDER BYで並び替え、LIMITとOFFSETでページング。CSVの成績データを使って結果セットを整える4構文を実行しながら学べます。
本記事で使うデータ — 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 行のデータです。
DISTINCT — 重複行を除いて取り出す
SELECTの結果に同じ値の行が複数回含まれることがあります。たとえばscoreテーブルからname列だけを取り出すと、Alice / Bob / Carol / Dave / Eve の 5 名がそれぞれ 3 科目分、計 15 行返ります。
SELECT DISTINCT 列, ...の形に書くと、結果セットの中で重複している行をまとめて 1 行に圧縮できます。複数列を指定した場合は「列の組み合わせ」が同じ行を重複と見なします。
-- 受験者の名前を重複なく一覧で取り出す
SELECT DISTINCT name FROM score;
-- 受験した科目を重複なく一覧で取り出す
SELECT DISTINCT subject FROM score;
-- 「名前と科目」の組み合わせで重複除去(= 全 15 行が一意)
SELECT DISTINCT name, subject FROM score;
ORDER BY — 結果を並び替える
SQL は行の順序を保証しないのが基本仕様で、SELECT * FROM score;のように書いてもどの順番で行が返るかは DB の実装に任されます。結果を意図通りの順序で並べたいときはORDER BY 列 [ASC|DESC]を付けます。
- ASC(昇順 / 小 → 大)が既定値で、省略可
- DESC(降順 / 大 → 小)は明示的に書く
- カンマ区切りで複数列を指定すると、第 1 列が同じ行は第 2 列で並べる、という多段ソートになります
-- 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 BYはWHEREのあと、LIMITの前に置くのが正しい順序です。SELECT 列 FROM 表 WHERE 条件 ORDER BY 列 DESC LIMIT N;の並びを覚えておくと迷いません。
- ORDER BYの右辺には列番号(ORDER BY 2 DESCで SELECT した 2 つ目の列で並べる)も書けますが、可読性が落ちるので列名で書くのが主流です。
- 文字列の並び順は本講座のコンソールでは大文字 → 小文字の順(ASCII 順)になります。DB によっては'A'と'a'を同等に扱う場合もあります。
LIMIT と OFFSET — 件数を絞ってページングする
結果セットが 100 行・1 万行と大きくなると、画面に全部出すと重くなり、ユーザーも見切れません。LIMIT Nを付けると先頭から N 行だけを取り出せます。これにOFFSET Mを組み合わせると、先頭 M 行を読み飛ばしてから N 行を取り出せるので、「6〜10 件目」「11〜20 件目」のようにページングができます。
-- 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 ページの件数 | OFFSET | LIMIT | 対象順位 |
|---|---|---|---|---|
| 1 | 5 | 0 | 5 | 1〜5 位 |
| 2 | 5 | 5 | 5 | 6〜10 位 |
| 3 | 5 | 10 | 5 | 11〜15 位 |
| 1 | 10 | 0 | 10 | 1〜10 位 |
| 2 | 10 | 10 | 10 | 11〜20 位 |
| 1 | 20 | 0 | 20 | 1〜20 位 |
ORDER BY なしの LIMIT は順序が保証されない
SELECT * FROM score LIMIT 5;のようにORDER BYを省いてLIMITだけを書くと、どの 5 行が返るかは DB の実装に任されます。SQLite のように挿入順で返ることが多い DB でも、SQL の規格上は順序は不定です。MySQL / PostgreSQL ではインデックスや実行計画の都合で別の行が返ることがあります。
ランキング・ページング・「先頭 N 件」のような順序が意味を持つ取得には、必ずORDER BYを付けてからLIMITを書きます。
理解度チェック
まずは1問ずつ答えてみましょう。
Q2SELECT name, score FROM score ORDER BY score DESC;の結果として正しいものはどれですか。
Q3SELECT * FROM score ORDER BY score DESC LIMIT 5 OFFSET 10;を実行したときに返る行として正しいものはどれですか。