コマンド道場

LIMIT / FETCH FIRST の使い方

並べたあと、上から n 行だけ残る

shain並べ替えた社員

namesalary
鈴木980000
佐藤720000
山田700000
清水650000
加藤610000
中村530000

LIMIT 3取り出した結果

namesalary
鈴木980000
佐藤720000
山田700000

LIMIT 3

  • 取り消し線= 結果に出てこない行
  • 並べ替えた社員 18 行 → 取り出した結果 315 行が消えます)

取り消し線の行は「並びとしては下にあるので返らない行」です。並び順が変われば、残る行も変わります。

LIMIT返す件数を絞ります。処理の最後に効くので、絞り込みも並べ替えも済んだあとの結果を、上から切り取る形になります。⚠️ 並び順を決めていないと、何が返るかは決まりません。 ここが最大の落とし穴です。

この書き方が使えない製品があります そのまま使える: PostgreSQL / MySQL / MariaDB / SQLite

  • SQL Server では使えませんLIMIT n
  • Oracle Database では使えませんLIMIT n
  • IBM Db2 では使えませんLIMIT n

製品ごとの対応表(実測)を見る

このページの実行結果と図は、すべて本物のデータベースに同じ SQL を流して得たものです。手で書いた「たぶんこうなる」ではありません。

01LIMIT は最後に効く

結論: 処理の順番は `FROM` → `WHERE` → `GROUP BY` → `HAVING` → `SELECT` → `ORDER BY` → `LIMIT` です。

LIMIT は並べ替えたあとの結果を上から切るだけです。したがって除きたい行は `WHERE` で先に落としておく必要があります。

「上位 3 件を取ってから条件で絞る」という順序にはできません。先に絞ってから上位を取ります。

1 行ずつ、何をしているか
  1. SELECT name, salary何を出すか
  2. FROM shainどの表を見るか
  3. WHERE taishoku_on IS NULL① 先に絞る
  4. ORDER BY salary DESC, shain_id② 並べる(同額の決着も)
  5. LIMIT 3③ 上から 3 行

①②③ の順に効きます。② を書かないと、③ が何を返すかは決まりません。

給与が高い上位 3 名
SELECT name, salary FROM shain ORDER BY salary DESC, shain_id LIMIT 3;
namesalary
鈴木980000
佐藤720000
山田700000

3

並べ替えてから上から 3 行を取っています。

⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表

退職者を除いてから上位 3 名
SELECT name, salary FROM shain WHERE taishoku_on IS NULL ORDER BY salary DESC, shain_id LIMIT 3;
namesalary
鈴木980000
佐藤720000
山田700000

3

この表では上位 3 名に退職者がいないので結果は同じですが、母集団が違えば結果も変わります。条件は必ず先に書いてください。

⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表

02⚠️ 並び順を決めないと結果が定まらない

結論: `ORDER BY` の無い `LIMIT` は、どの行が返るか決まっていません。

「とりあえず 3 件見たい」だけなら構いませんが、上位 3 件を取っているつもりで書くと誤りです。並びが保証されていない以上、「上位」という概念自体が成立しません。

さらに、第 1 キーが同じ行があるときは、第 2 キーまで決めないと安定しません。この表には給与が同額の社員がいるので、`salary` だけでは 6 位以降が入れ替わりえます

⚠️ 並び順を指定しない
SELECT name, salary FROM shain LIMIT 3;
namesalary
鈴木980000
佐藤720000
田中520000

3

3 行返りますが、これが「上位 3 名」である保証はどこにもありません。

⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表

同額の社員がいる範囲まで取る
SELECT name, salary FROM shain ORDER BY salary DESC LIMIT 7;
namesalary
鈴木980000
佐藤720000
山田700000
清水650000
加藤610000
中村530000
伊藤530000

7

6 位と 7 位が同額です。第 2 キーが無いので、この 2 人の順番は決まっていません。

⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表

第 2 キーで決着を付ける
SELECT shain_id, name, salary FROM shain ORDER BY salary DESC, shain_id LIMIT 7;
shain_idnamesalary
1鈴木980000
2佐藤720000
8山田700000
14清水650000
6加藤610000
4中村530000
10伊藤530000

7

shain_id を足したので、何度実行しても同じ 7 行・同じ順番になります。

⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表

03OFFSET でページ送りする

結論: `OFFSET` は「先頭から何件読み飛ばすか」です。

位置ではなく件数なので、n 番目から欲しいときは `OFFSET n-1` です。1 つずれる間違いが起きやすいところです。

⚠️ ページ送りでは並び順の確定が必須です。順番が実行ごとに変わると、同じ行が 2 ページに出たり、どのページにも出なかったりします。一意な列を最後のキーに入れてください。

1 ページ目(1〜3 位)
SELECT shain_id, name, salary FROM shain ORDER BY salary DESC, shain_id LIMIT 3;
shain_idnamesalary
1鈴木980000
2佐藤720000
8山田700000

3

OFFSET を書かなければ先頭からです。

⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表

2 ページ目(4〜6 位)
SELECT shain_id, name, salary FROM shain ORDER BY salary DESC, shain_id LIMIT 3 OFFSET 3;
shain_idnamesalary
14清水650000
6加藤610000
4中村530000

3

3 件読み飛ばして次の 3 件です。4 番目から欲しいので OFFSET は 3 になります。

⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表

⚠️ 1 つずれた例
SELECT shain_id, name, salary FROM shain ORDER BY salary DESC, shain_id LIMIT 3 OFFSET 4;
shain_idnamesalary
6加藤610000
4中村530000
10伊藤530000

3

5 番目から始まっています。「4 番目から」を OFFSET 4 と書くとこうなります。

⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表

04⚠️ 製品ごとに書き方が違う

結論: `LIMIT` は標準 SQL ではありません。標準は `FETCH FIRST … ROWS ONLY` です。

実際には多くの製品が LIMIT を採り入れていますが、無い製品もあります

  • PostgreSQL / MySQL / MariaDB / SQLite … LIMIT n
  • Oracle / Db2 … FETCH FIRST n ROWS ONLY
  • SQL Server … ORDER BY のあとに OFFSET 0 ROWS FETCH NEXT n ROWS ONLY

PostgreSQL は両方書けます。ただし MySQL と SQLite は `FETCH FIRST` を受け付けないため、1 つの書き方で全部をまかなうことはできません。

LIMIT で書く
SELECT name, salary FROM shain ORDER BY salary DESC, shain_id LIMIT 3;
namesalary
鈴木980000
佐藤720000
山田700000

3

PostgreSQL・MySQL・MariaDB・SQLite で通ります。

⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表

標準 SQL の書き方
SELECT name, salary FROM shain ORDER BY salary DESC, shain_id FETCH FIRST 3 ROWS ONLY;
namesalary
鈴木980000
佐藤720000
山田700000

3

同じ結果です。PostgreSQL は両方を受け付けます。Oracle と Db2 ではこちらを使います。

⚠️ この書き方は MySQL / SQLite / SQL Server では使えません(FETCH FIRST n ROWS ONLY)。製品ごとの対応表

SQL Server と同じ形で書く
SELECT name, salary FROM shain ORDER BY salary DESC, shain_id OFFSET 3 ROWS FETCH NEXT 3 ROWS ONLY;
namesalary
清水650000
加藤610000
中村530000

3

読み飛ばしと件数を標準の書き方で指定しています。SQL Server ではこの形が必要です。

⚠️ この書き方は MySQL / SQLite では使えません(OFFSET n ROWS FETCH NEXT n ROWS ONLY)。製品ごとの対応表

自分で打ってみる

このページの例と同じデータが入った本物のデータベースを、この場(あなたのブラウザの中)で起動できます。打った SQL がサーバーへ送られることはありません。

押すと初回だけ約 9MB を読み込みます(2 回目以降はキャッシュされます)。

解いてみる

読んだだけでは書けるようになりません。実行結果で採点します。

関連するトピック

根拠(一次情報)