LIMIT / FETCH FIRST の使い方
shain並べ替えた社員
| name | salary |
|---|---|
| 鈴木 | 980000 |
| 佐藤 | 720000 |
| 山田 | 700000 |
| 清水 | 650000✕ |
| 加藤 | 610000✕ |
| 中村 | 530000✕ |
| … | |
LIMIT 3取り出した結果
| name | salary |
|---|---|
| 鈴木 | 980000 |
| 佐藤 | 720000 |
| 山田 | 700000 |
LIMIT 3
- 取り消し線= 結果に出てこない行
- 並べ替えた社員 18 行 → 取り出した結果 3 行(15 行が消えます)
取り消し線の行は「並びとしては下にあるので返らない行」です。並び順が変われば、残る行も変わります。
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 件を取ってから条件で絞る」という順序にはできません。先に絞ってから上位を取ります。
SELECT name, salary何を出すかFROM shainどの表を見るかWHERE taishoku_on IS NULL① 先に絞るORDER BY salary DESC, shain_id② 並べる(同額の決着も)LIMIT 3③ 上から 3 行
①②③ の順に効きます。② を書かないと、③ が何を返すかは決まりません。
SELECT name, salary FROM shain ORDER BY salary DESC, shain_id LIMIT 3;| name | salary |
|---|---|
| 鈴木 | 980000 |
| 佐藤 | 720000 |
| 山田 | 700000 |
(3 行)
並べ替えてから上から 3 行を取っています。
⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表
SELECT name, salary FROM shain WHERE taishoku_on IS NULL ORDER BY salary DESC, shain_id LIMIT 3;| name | salary |
|---|---|
| 鈴木 | 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;| name | salary |
|---|---|
| 鈴木 | 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;| name | salary |
|---|---|
| 鈴木 | 980000 |
| 佐藤 | 720000 |
| 山田 | 700000 |
| 清水 | 650000 |
| 加藤 | 610000 |
| 中村 | 530000 |
| 伊藤 | 530000 |
(7 行)
6 位と 7 位が同額です。第 2 キーが無いので、この 2 人の順番は決まっていません。
⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表
SELECT shain_id, name, salary FROM shain ORDER BY salary DESC, shain_id LIMIT 7;| shain_id | name | salary |
|---|---|---|
| 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 ページに出たり、どのページにも出なかったりします。一意な列を最後のキーに入れてください。
SELECT shain_id, name, salary FROM shain ORDER BY salary DESC, shain_id LIMIT 3;| shain_id | name | salary |
|---|---|---|
| 1 | 鈴木 | 980000 |
| 2 | 佐藤 | 720000 |
| 8 | 山田 | 700000 |
(3 行)
OFFSET を書かなければ先頭からです。
⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表
SELECT shain_id, name, salary FROM shain ORDER BY salary DESC, shain_id LIMIT 3 OFFSET 3;| shain_id | name | salary |
|---|---|---|
| 14 | 清水 | 650000 |
| 6 | 加藤 | 610000 |
| 4 | 中村 | 530000 |
(3 行)
3 件読み飛ばして次の 3 件です。4 番目から欲しいので OFFSET は 3 になります。
⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表
SELECT shain_id, name, salary FROM shain ORDER BY salary DESC, shain_id LIMIT 3 OFFSET 4;| shain_id | name | salary |
|---|---|---|
| 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 つの書き方で全部をまかなうことはできません。
SELECT name, salary FROM shain ORDER BY salary DESC, shain_id LIMIT 3;| name | salary |
|---|---|
| 鈴木 | 980000 |
| 佐藤 | 720000 |
| 山田 | 700000 |
(3 行)
PostgreSQL・MySQL・MariaDB・SQLite で通ります。
⚠️ この書き方は SQL Server / Oracle Database / IBM Db2 では使えません(LIMIT n)。製品ごとの対応表
SELECT name, salary FROM shain ORDER BY salary DESC, shain_id FETCH FIRST 3 ROWS ONLY;| name | salary |
|---|---|
| 鈴木 | 980000 |
| 佐藤 | 720000 |
| 山田 | 700000 |
(3 行)
同じ結果です。PostgreSQL は両方を受け付けます。Oracle と Db2 ではこちらを使います。
⚠️ この書き方は MySQL / SQLite / SQL Server では使えません(FETCH FIRST n ROWS ONLY)。製品ごとの対応表
SELECT name, salary FROM shain ORDER BY salary DESC, shain_id OFFSET 3 ROWS FETCH NEXT 3 ROWS ONLY;| name | salary |
|---|---|
| 清水 | 650000 |
| 加藤 | 610000 |
| 中村 | 530000 |
(3 行)
読み飛ばしと件数を標準の書き方で指定しています。SQL Server ではこの形が必要です。
⚠️ この書き方は MySQL / SQLite では使えません(OFFSET n ROWS FETCH NEXT n ROWS ONLY)。製品ごとの対応表
自分で打ってみる
このページの例と同じデータが入った本物のデータベースを、この場(あなたのブラウザの中)で起動できます。打った SQL がサーバーへ送られることはありません。
押すと初回だけ約 9MB を読み込みます(2 回目以降はキャッシュされます)。
解いてみる
読んだだけでは書けるようになりません。実行結果で採点します。
関連するトピック
- ORDER BY 句LIMIT の前に並び順を確定させないと、何が返るか決まりません。
- ROW_NUMBER / RANK / DENSE_RANK(練習問題)同順位まで含めて上位を取りたいときは、順位関数を使います。
- WHERE 句除きたい行は LIMIT ではなく WHERE で先に落とします。
根拠(一次情報)
- PostgreSQL 18 マニュアル: LIMIT と OFFSET一次情報・確認 2026-08-02
- PostgreSQL 18 マニュアル: SELECT(LIMIT 句)一次情報・確認 2026-08-02