Query Go
件数制限の書き方 - 件数制限の方言 (LIMIT / TOP / FETCH) の使い方・オプション・サンプル

件数制限の書き方 - 件数制限の方言 (LIMIT / TOP / FETCH)

SELECT の返却行数を制限する書き方は RDBMS ごとに異なる。LIMIT / TOP / FETCH FIRST の違いと移植のコツを解説

概念図

件数制限の方言 (LIMIT / TOP / FETCH) diagram

構文

sql
SELECT ... LIMIT n  /  SELECT TOP n ...  /  SELECT ... FETCH FIRST n ROWS ONLY

サンプル

3 通りの書き方で先頭 10 行 (+20 行スキップ) を取得する例

sql
-- PostgreSQL / MySQL / SQLite
SELECT * FROM products ORDER BY id LIMIT 10 OFFSET 20;

-- SQL Server
SELECT TOP 10 * FROM products ORDER BY id;

-- ANSI 標準 (PostgreSQL / SQL Server / Oracle 12c+ が対応)
SELECT * FROM products
ORDER BY id
OFFSET 20 ROWS FETCH FIRST 10 ROWS ONLY;

件数制限はなぜ方言が多いのか

SQL 標準では元々「先頭 N 行だけ取る」構文が定義されていませんでした。そのため各 RDBMS が独自に拡張した結果、LIMITTOPROWNUM など記法が分かれました。

SQL:2008 でようやく OFFSET ... FETCH FIRST n ROWS ONLY という標準構文が定義され、PostgreSQL / SQL Server / Oracle (12c 以降) が対応しています。しかし現場では歴史的経緯から方言の方が多く使われています。

RDBMS 別比較表

RDBMS基本の書き方OFFSET 併用
PostgreSQLLIMIT 10LIMIT 10 OFFSET 20
MySQLLIMIT 10LIMIT 20, 10 または LIMIT 10 OFFSET 20
SQLiteLIMIT 10LIMIT 10 OFFSET 20
SQL ServerSELECT TOP 10 ...OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY (2012+)
OracleFETCH FIRST 10 ROWS ONLY (12c+) / ROWNUM <= 10 (旧)OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY
ANSI 標準FETCH FIRST 10 ROWS ONLYOFFSET 20 ROWS FETCH FIRST 10 ROWS ONLY

ORDER BY なしの LIMIT は危険

ORDER BY を付けない LIMIT/TOP/FETCH は、どの行が返るかが未定義です。同じクエリでもプランや物理配置が変わると結果が変わります。

ページネーションやランキング等で LIMIT を使う場合は、必ず一意に決まる ORDER BY(タイブレーカーを含む主キー)を付けましょう。

sql
-- 悪い例: 順序が不定
SELECT * FROM orders LIMIT 10;

-- 良い例: 主キーをタイブレーカーに
SELECT * FROM orders
ORDER BY created_at DESC, id DESC
LIMIT 10;

移植時の落とし穴

  • MySQL の LIMIT 20, 10: 第1引数が OFFSET、第2が行数。他 RDBMS の LIMIT 10 OFFSET 20 とは引数順が真逆なので機械的置換は危険
  • SQL Server の TOP に OFFSET は無い: ページネーションしたいなら OFFSET ... FETCH NEXT (2012 以降) が必須
  • Oracle の ROWNUM: WHERE 句で評価されるため ORDER BY との組合せは副問い合わせが必要。12c 以降は FETCH を使うのが素直
  • OFFSET が大きいとき: どの RDBMS でも「先頭からスキップ」するので、OFFSET が数万を超えるとキーセットページネーション(WHERE id > ?)の方が速い

関連トピック