【SQL】LIMIT句の使い方|OFFSET・ページネーション・RDBMS別構文・パフォーマンス対策

【SQL】LIMIT句の使い方|OFFSET・ページネーション・RDBMS別構文・パフォーマンス対策 SQL

SQLで「先頭の5件だけ取得したい」「11件目から20件目までを表示したい」といった場面は頻繁にあります。Webアプリケーションのページネーション(ページ送り)や、ランキングの上位N件表示など、取得件数を制限する操作はデータベース操作の基本です。

SQLでは LIMIT句 を使うことで取得する行数を制限できます。ただし、LIMIT句はSQL標準ではなく、RDBMS(データベース製品)によって構文が異なります。この記事では、LIMIT句の基本から OFFSET によるページネーションOracle・SQL Server・MySQL・PostgreSQL の構文比較大量データでのパフォーマンス対策まで体系的に解説します。

この記事で学べること

  • LIMIT句の基本構文と取得件数の指定方法
  • ORDER BY + LIMIT で上位N件を取得する方法
  • LIMIT + OFFSET でページネーションを実装する方法
  • MySQL / PostgreSQL / Oracle / SQL Server の構文比較
  • OFFSETを使ったページネーションの実装パターン
  • 大きいOFFSETが遅くなる理由とカーソルベースの対策
  • 最新N件・TOP10・ランダム取得などの実務パターン
  • ORDER BYなしのLIMITやOFFSETのずれなど、よくあるミス
スポンサーリンク

サンプルデータの準備

この記事では以下の products テーブルを使って解説します。

▶ CREATE TABLE + INSERT文(クリックで展開)
CREATE TABLE products (
    id         INT PRIMARY KEY,
    name       VARCHAR(50),
    category   VARCHAR(20),
    price      INT,
    stock      INT,
    created_at DATE
);

INSERT INTO products VALUES
(1,  'ノートPC',       '電子機器', 89000,  15, '2024-01-10'),
(2,  'マウス',         '周辺機器', 3500,   120, '2024-01-15'),
(3,  'キーボード',     '周辺機器', 8900,   85, '2024-02-01'),
(4,  'モニター',       '電子機器', 45000,  30, '2024-02-10'),
(5,  'USBメモリ',      '周辺機器', 1200,   200, '2024-02-20'),
(6,  'Webカメラ',      '周辺機器', 5600,   60, '2024-03-01'),
(7,  'タブレット',     '電子機器', 55000,  25, '2024-03-15'),
(8,  'ヘッドセット',   '周辺機器', 12000,  45, '2024-04-01'),
(9,  '外付けSSD',      '周辺機器', 9800,   70, '2024-04-10'),
(10, 'デスクトップPC', '電子機器', 120000, 10, '2024-05-01'),
(11, 'スピーカー',     '周辺機器', 7800,   55, '2024-05-15'),
(12, 'プリンター',     '電子機器', 35000,  20, '2024-06-01');
id name category price stock created_at
1 ノートPC 電子機器 89,000 15 2024-01-10
2 マウス 周辺機器 3,500 120 2024-01-15
3 キーボード 周辺機器 8,900 85 2024-02-01
4 モニター 電子機器 45,000 30 2024-02-10
5 USBメモリ 周辺機器 1,200 200 2024-02-20
6 Webカメラ 周辺機器 5,600 60 2024-03-01
7 タブレット 電子機器 55,000 25 2024-03-15
8 ヘッドセット 周辺機器 12,000 45 2024-04-01
9 外付けSSD 周辺機器 9,800 70 2024-04-10
10 デスクトップPC 電子機器 120,000 10 2024-05-01
11 スピーカー 周辺機器 7,800 55 2024-05-15
12 プリンター 電子機器 35,000 20 2024-06-01

LIMIT句の基本構文

取得件数の指定

LIMIT句はSELECT文の末尾に記述し、取得する行数の上限を指定します。

LIMIT句の基本構文
SELECT 列名1, 列名2, ...
FROM テーブル名
LIMIT 取得件数;

productsテーブルから先頭の5件だけを取得してみましょう。

先頭5件を取得
SELECT id, name, price
FROM products
LIMIT 5;
id name price
1 ノートPC 89,000
2 マウス 3,500
3 キーボード 8,900
4 モニター 45,000
5 USBメモリ 1,200

注意

ORDER BYを指定しない場合、どの行が返されるかは不定です。テーブルの物理的な格納順に依存するため、INSERT順と同じとは限りません。確実に「先頭N件」を取得したい場合は、必ずORDER BYと組み合わせてください。

ORDER BY + LIMIT の組み合わせ(TOP N)

実務では ORDER BY で並び替えてから LIMIT で件数を制限する のが基本パターンです。「価格が高い順に3件」「最新の5件」といった上位N件の取得ができます。

価格が高い順に上位3件を取得
SELECT id, name, price
FROM products
ORDER BY price DESC
LIMIT 3;
id name price
10 デスクトップPC 120,000
1 ノートPC 89,000
7 タブレット 55,000

SQLの記述順と処理順序を確認しておきましょう。

SQLの処理順序

1. FROM(テーブルの選択)
2. WHERE(行の絞り込み)
3. GROUP BY(グループ化)
4. HAVING(グループの絞り込み)
5. SELECT(列の選択)
6. ORDER BY(並び替え)
7. LIMIT(件数制限)← 最後に実行される

LIMIT句は最後に処理されるため、WHERE句で絞り込んだ結果やORDER BYで並び替えた結果に対して件数制限が適用されます。

LIMIT + OFFSET でページネーション

OFFSET句を組み合わせると、先頭から指定した行数をスキップしてデータを取得できます。これがページネーション(ページ送り)の基本です。

LIMIT + OFFSET の構文
SELECT 列名1, 列名2, ...
FROM テーブル名
ORDER BY 列名
LIMIT 取得件数 OFFSET スキップ件数;

-- 省略記法(MySQL)
SELECT 列名 FROM テーブル名
LIMIT スキップ件数, 取得件数;

例えば、価格の安い順に並べて「4件目から3件」を取得する場合はこうなります。

4件目から3件取得(OFFSETは0始まり)
SELECT id, name, price
FROM products
ORDER BY price ASC
LIMIT 3 OFFSET 3;
id name price
6 Webカメラ 5,600
11 スピーカー 7,800
3 キーボード 8,900

OFFSETは 0始まり です。OFFSET 0 は先頭から、OFFSET 3 は4番目の行からデータを取得します。次の図でイメージを確認しましょう。

OFFSET のイメージ

全12件のデータ(価格昇順):
[1] USBメモリ 1,200 ← OFFSET 0(ここから)
[2] マウス 3,500
[3] Webカメラ 5,600 ← LIMIT 3 OFFSET 0 はここまで
[4] スピーカー 7,800 ← OFFSET 3(ここから)
[5] キーボード 8,900
[6] 外付けSSD 9,800 ← LIMIT 3 OFFSET 3 はここまで
[7] ヘッドセット 12,000 ← OFFSET 6(ここから)

RDBMS別の件数制限構文

LIMIT句は SQL標準の構文ではありません。MySQLとPostgreSQLではLIMITが使えますが、OracleやSQL Serverでは別の構文を使います。ここでは主要なRDBMSの構文を比較します。

MySQL / PostgreSQL:LIMIT … OFFSET

MySQLとPostgreSQLは同じ構文で LIMIT + OFFSET が使えます。

MySQL / PostgreSQL
-- 基本(先頭N件)
SELECT * FROM products LIMIT 10;

-- OFFSET付き
SELECT * FROM products LIMIT 10 OFFSET 20;

-- MySQL省略記法(OFFSET, LIMITの順に注意)
SELECT * FROM products LIMIT 20, 10;

MySQL省略記法の注意

LIMIT 20, 10 と書くと「20件スキップして10件取得」です。第1引数がOFFSET、第2引数がLIMITで、LIMIT 10 OFFSET 20 と順序が逆になります。混乱しやすいので、LIMIT … OFFSET … 形式を推奨します。

Oracle:FETCH FIRST … ROWS ONLY / ROWNUM

Oracleでは 12c以降 で FETCH FIRST 構文(SQL:2008標準準拠)が使えます。それ以前のバージョンではROWNUMを使います。

Oracle 12c以降(FETCH FIRST)
-- 先頭N件
SELECT * FROM products
ORDER BY price DESC
FETCH FIRST 10 ROWS ONLY;

-- OFFSET付き
SELECT * FROM products
ORDER BY price DESC
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY;
Oracle 11g以前(ROWNUM)
-- 先頭N件(サブクエリが必要)
SELECT * FROM (
    SELECT * FROM products
    ORDER BY price DESC
)
WHERE ROWNUM <= 10;

-- OFFSET付き(二重サブクエリ)
SELECT * FROM (
    SELECT a.*, ROWNUM AS rn FROM (
        SELECT * FROM products
        ORDER BY price DESC
    ) a WHERE ROWNUM <= 30
)
WHERE rn > 20;

SQL Server:TOP / OFFSET-FETCH

SQL Serverでは TOP で先頭N件を取得し、OFFSET-FETCH(2012以降)でページネーションを行います。

SQL Server
-- TOP(先頭N件)
SELECT TOP 10 * FROM products
ORDER BY price DESC;

-- OFFSET-FETCH(ページネーション、2012以降)
SELECT * FROM products
ORDER BY price DESC
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY;

RDBMS別構文の比較表

各RDBMSの件数制限構文をまとめます。

機能 MySQL PostgreSQL Oracle 12c+ SQL Server 2012+
先頭N件 LIMIT N LIMIT N FETCH FIRST N ROWS ONLY TOP N
OFFSET付き LIMIT N OFFSET M LIMIT N OFFSET M OFFSET M ROWS FETCH NEXT N ROWS ONLY OFFSET M ROWS FETCH NEXT N ROWS ONLY
ORDER BY必須 任意 任意 OFFSET使用時は必須 OFFSET使用時は必須
SQL標準準拠 非標準 非標準 SQL:2008準拠 SQL:2008準拠

ポイント

Oracle 12c+ と SQL Server 2012+ の OFFSET ... FETCH 構文は同じ書き方です。これは SQL:2008標準 に準拠した構文で、将来的にはこの書き方が主流になると予想されます。PostgreSQLもこの構文をサポートしています。

OFFSETを使ったページネーション

Webアプリケーションで最もよく使われるLIMIT句の活用例がページネーション(ページ送り)です。1ページに表示する件数を決めて、ページ番号に応じてOFFSETを計算します。

基本のページネーション実装

1ページあたり5件表示する場合の各ページのSQLを見てみましょう。

ページネーションの各ページ
-- 1ページ目(1〜5件目)
SELECT * FROM products
ORDER BY id
LIMIT 5 OFFSET 0;

-- 2ページ目(6〜10件目)
SELECT * FROM products
ORDER BY id
LIMIT 5 OFFSET 5;

-- 3ページ目(11〜12件目)
SELECT * FROM products
ORDER BY id
LIMIT 5 OFFSET 10;

3ページ目はデータが2件しかないため、2件だけが返されます。LIMITで指定した件数よりデータが少ない場合は、存在する分だけが返されます(エラーにはなりません)。

ページ番号からOFFSETを計算する方法

ページネーションでは、ページ番号(page)と1ページあたりの表示件数(per_page)からOFFSETを算出します。計算式は次の通りです。

OFFSET の計算式

OFFSET = (ページ番号 – 1) × 1ページあたりの件数

ページ番号 計算式 OFFSET値 取得範囲
1 (1-1) x 5 0 1〜5件目
2 (2-1) x 5 5 6〜10件目
3 (3-1) x 5 10 11〜15件目
N (N-1) x 5 (N-1) x 5

アプリケーション側(PHP、Python、Javaなど)のコードでは、次のように実装します。

アプリケーション側の実装例(疑似コード)
-- ページ番号: :page(1始まり)
-- 表示件数: :per_page
SELECT * FROM products
ORDER BY id
LIMIT :per_page
OFFSET (:page - 1) * :per_page;

総件数の取得(COUNT + LIMIT)

ページネーションUIを構築するには、総件数(総ページ数の算出用)と該当ページのデータの両方が必要です。通常は2つのクエリを実行します。

総件数とデータの取得
-- 1. 総件数を取得
SELECT COUNT(*) AS total_count
FROM products;

-- 2. 該当ページのデータを取得
SELECT * FROM products
ORDER BY id
LIMIT 5 OFFSET 0;

-- 総ページ数 = CEIL(total_count / per_page)
-- 例: CEIL(12 / 5) = 3ページ

ポイント

WHERE句で絞り込みを行っている場合は、COUNT(*)にも同じWHERE条件を付ける必要があります。条件なしのCOUNT(*)では正しい総ページ数が計算できません。

WHERE条件付きの場合
-- 総件数(条件付き)
SELECT COUNT(*) AS total_count
FROM products
WHERE category = '周辺機器';

-- データ取得(同じ条件)
SELECT * FROM products
WHERE category = '周辺機器'
ORDER BY id
LIMIT 5 OFFSET 0;

パフォーマンスの注意点

LIMIT + OFFSET によるページネーションはシンプルで実装しやすい反面、データ量が増えるとパフォーマンスが大幅に低下する場合があります。ここでは原因と対策を解説します。

大きいOFFSETが遅い理由

例えば10万件のテーブルで LIMIT 10 OFFSET 99990(最後のページ)を実行すると、データベースは内部的に100,000行を読み取り、そのうち99,990行を捨て、残りの10行だけを返すという処理を行います。

OFFSETが大きいと遅い
-- OFFSET 0: 高速(先頭10件だけ読む)
SELECT * FROM large_table ORDER BY id LIMIT 10 OFFSET 0;

-- OFFSET 99990: 低速(100,000行を読んで99,990行捨てる)
SELECT * FROM large_table ORDER BY id LIMIT 10 OFFSET 99990;

つまり、OFFSETの値が大きいほど処理が遅くなるのです。これはページ番号が後ろになるほど体感速度が落ちる原因です。

OFFSET値 内部で読む行数 返す行数 速度
0 10 10 高速
1,000 1,010 10 普通
10,000 10,010 10 やや遅い
99,990 100,000 10 非常に遅い

カーソルベースのページネーション(WHERE id > 最後のID)

OFFSETの問題を解決する方法が カーソルベースのページネーション(keyset pagination)です。前のページの最後のレコードのIDを基準にして次のページを取得します。

カーソルベースのページネーション
-- 1ページ目(通常通り)
SELECT * FROM products
ORDER BY id
LIMIT 5;
-- 結果: id = 1, 2, 3, 4, 5(最後のIDは5)

-- 2ページ目(id > 5 で絞り込み)
SELECT * FROM products
WHERE id > 5
ORDER BY id
LIMIT 5;
-- 結果: id = 6, 7, 8, 9, 10(最後のIDは10)

-- 3ページ目(id > 10 で絞り込み)
SELECT * FROM products
WHERE id > 10
ORDER BY id
LIMIT 5;

この方法では、何ページ目であっても常にインデックスを使って高速にデータを取得できます。OFFSETのように前の行を読み飛ばす必要がありません。

インデックスの活用

LIMIT + ORDER BYのパフォーマンスを最大化するには、ORDER BY で指定するカラムにインデックスを作成することが重要です。

インデックスの作成
-- ORDER BY + LIMITで使うカラムにインデックスを作成
CREATE INDEX idx_products_price ON products(price);

-- 複合インデックス(WHERE + ORDER BY + LIMITの場合)
CREATE INDEX idx_products_cat_price
ON products(category, price);

インデックスがあれば、データベースはテーブル全体をスキャンせずに必要な行だけを効率的に取得できます。特にORDER BY + LIMITの組み合わせでは、インデックスの有無で実行速度が大きく変わります。

OFFSET vs カーソルベースの比較表

比較項目 OFFSET方式 カーソルベース方式
実装の簡単さ 簡単 やや複雑
大量データの速度 OFFSETが大きいと遅い 常に高速
任意ページへのジャンプ 可能 不可(順次のみ)
データ追加・削除時 重複・欠落の可能性あり 一貫性が保たれる
適用場面 管理画面、少量データ SNSフィード、無限スクロール

使い分けの目安

数千件程度のデータならOFFSET方式で十分です。数万件以上になる場合や、TwitterやInstagramのような無限スクロールUIを実装する場合は、カーソルベース方式を検討してください。

実務でよく使うパターン

ここからは、実際の開発現場でよく使われるLIMIT句の活用パターンを紹介します。

最新N件の取得

新着情報やお知らせの表示で最も多いパターンです。日付の降順(新しい順)に並べてLIMITで件数を制限します。

最新5件の商品を取得
SELECT id, name, price, created_at
FROM products
ORDER BY created_at DESC
LIMIT 5;
id name price created_at
12 プリンター 35,000 2024-06-01
11 スピーカー 7,800 2024-05-15
10 デスクトップPC 120,000 2024-05-01
9 外付けSSD 9,800 2024-04-10
8 ヘッドセット 12,000 2024-04-01

売上TOP10(ランキング)

集計関数と組み合わせてランキングを作成する例です。GROUP BYで集計した結果にORDER BY + LIMITを適用します。

カテゴリ別の在庫数ランキング
SELECT
    category,
    SUM(stock) AS total_stock,
    COUNT(*) AS product_count
FROM products
GROUP BY category
ORDER BY total_stock DESC
LIMIT 3;
category total_stock product_count
周辺機器 635 7
電子機器 100 5

ランダムに1件取得(ORDER BY RAND())

ランダムな1件を取得するには ORDER BY RAND()LIMIT 1 を組み合わせます。

ランダムに1件取得(MySQL)
SELECT * FROM products
ORDER BY RAND()
LIMIT 1;

ORDER BY RAND() の注意点

ORDER BY RAND() は全行にランダムな値を割り当ててソートするため、大量データでは非常に遅くなります。数万件以上のテーブルでは、以下のようにIDの範囲からランダムに取得する方が高速です。

高速なランダム取得(代替方法)
-- IDが連番の場合の高速な方法
SELECT * FROM products
WHERE id >= (
    SELECT FLOOR(
        RAND() * (SELECT MAX(id) FROM products)
    ) + 1
)
ORDER BY id
LIMIT 1;

サブクエリでのLIMIT

サブクエリ(副問合せ)の中でLIMITを使うことで、「最も高い商品の名前」や「最新の注文」などを取得できます。

サブクエリでLIMITを使用
-- 最も高価な商品と同じカテゴリの商品を取得
SELECT * FROM products
WHERE category = (
    SELECT category FROM products
    ORDER BY price DESC
    LIMIT 1
)
ORDER BY price DESC;
id name category price
10 デスクトップPC 電子機器 120,000
1 ノートPC 電子機器 89,000
7 タブレット 電子機器 55,000
4 モニター 電子機器 45,000
12 プリンター 電子機器 35,000

サブクエリで LIMIT 1 を使うと、スカラーサブクエリ(1行1列を返すサブクエリ)として利用でき、WHERE句の条件値として使えます。

UPDATE / DELETE でのLIMIT(MySQL限定)

MySQLでは、UPDATE文やDELETE文でもLIMIT句を使用できます。大量の行を一度に更新・削除するとロックが長時間保持されるため、バッチ処理で少しずつ処理する際に使います。

UPDATE / DELETE でのLIMIT(MySQL)
-- 古いデータを1000件ずつ削除(バッチ処理)
DELETE FROM access_logs
WHERE created_at < '2023-01-01'
LIMIT 1000;

-- 在庫を100件ずつ更新
UPDATE products
SET stock = 0
WHERE category = '廃止品'
LIMIT 100;

注意

UPDATE / DELETE での LIMIT は MySQL固有の機能 です。PostgreSQL、Oracle、SQL Server では使用できません。また、UPDATE / DELETE での LIMIT は ORDER BYと併用できません(MySQL 8.0時点)。どの行が処理されるかは不定のため、WHERE条件で確実に絞り込んでから使いましょう。

よくあるミスと注意点

LIMIT句を使う際に初心者がつまずきやすいポイントをまとめます。

ORDER BYなしのLIMITは順序不定

前述しましたが、非常に重要なので改めて強調します。ORDER BYを指定しない LIMIT は、どの行が返されるか保証されません

ORDER BYなしのLIMIT(非推奨)
-- 悪い例: どの5件が返されるか不定
SELECT * FROM products LIMIT 5;

-- 良い例: ORDER BYで順序を明示
SELECT * FROM products
ORDER BY id
LIMIT 5;

データの追加・削除やインデックスの再構築後に結果が変わる可能性があるため、再現性が必要な場面では必ず ORDER BY を付けましょう。ただし、「とりあえずデータの中身を確認したい」といったテスト目的であれば ORDER BY なしでも問題ありません。

OFFSET指定のずれ(0始まり vs 1始まり)

OFFSETは 0始まり です。「1件目から」取得したい場合は OFFSET 0(または省略)を指定します。

OFFSETの0始まりに注意
-- 間違い: 2件目からになってしまう
SELECT * FROM products
ORDER BY id
LIMIT 5 OFFSET 1;  -- 1件目がスキップされる

-- 正しい: 1件目から5件取得
SELECT * FROM products
ORDER BY id
LIMIT 5 OFFSET 0;  -- またはOFFSET省略
OFFSET値 スキップする行数 開始位置
0 0件 1件目から
1 1件 2件目から
5 5件 6件目から
10 10件 11件目から

LIMIT 0 の動作

LIMIT 0 を指定すると、結果は0件(空の結果セット)になります。エラーにはなりません。

LIMIT 0 の動作
-- 0件が返される(エラーにはならない)
SELECT * FROM products LIMIT 0;

-- 活用例: クエリの構文チェック(結果は不要だが構文を確認したい)
SELECT id, name, price, non_existent_column
FROM products
LIMIT 0;  -- カラムが存在しなければエラーになる

これは一見無意味に見えますが、アプリケーション開発ではSQLの構文チェック結果セットのカラム情報取得に使われることがあります。

GROUP BY + LIMIT の挙動

GROUP BYとLIMITを組み合わせる場合、LIMITはグループ化された後の結果に適用されます。「各グループから上位N件を取得する」という意味ではありません。

GROUP BY + LIMIT の挙動
-- カテゴリ別の集計から上位1グループだけ取得
SELECT category, COUNT(*) AS cnt
FROM products
GROUP BY category
ORDER BY cnt DESC
LIMIT 1;

-- 結果: 「周辺機器 7」(最も商品数が多いカテゴリ)

各グループから上位N件を取得したい場合

「各カテゴリから最も高い商品を1件ずつ取得」のような処理は、LIMITだけでは実現できません。ウィンドウ関数ROW_NUMBER() OVER (PARTITION BY ...) を使います。

各カテゴリから上位1件ずつ取得
SELECT * FROM (
    SELECT *,
        ROW_NUMBER() OVER (
            PARTITION BY category
            ORDER BY price DESC
        ) AS rn
    FROM products
) ranked
WHERE rn = 1;
id name category price rn
10 デスクトップPC 電子機器 120,000 1
8 ヘッドセット 周辺機器 12,000 1

MySQL省略記法の引数順序

MySQLの LIMIT offset, count 省略記法は引数の順序が直感に反するため、混同しやすいミスです。

MySQL省略記法の注意
-- LIMIT offset, count と LIMIT count OFFSET offset
LIMIT 10, 5   -- 10件スキップして5件取得
LIMIT 5 OFFSET 10  -- 同じ意味(こちらが読みやすい)

-- よくある間違い
LIMIT 5, 10   -- 意図: 5件取得 → 実際: 5件スキップして10件取得

推奨

可読性とRDBMS間の互換性を考慮し、LIMIT count OFFSET offset 形式を使うことを推奨します。省略記法 LIMIT offset, count はMySQLでしか使えず、引数の順序も紛らわしいです。

よくある質問(FAQ)

Q. LIMITとOFFSETの組み合わせでページネーションを実装するとき、大量データで遅くなります。解決策は?
A. OFFSET値が大きくなるほど全件スキャンが増えるため遅くなります。代替策はキーセットページネーション(カーソル方式):前ページの最後のIDを基準にWHERE id > last_id ORDER BY id LIMIT 10のようにします。インデックスが効きO(1)で取得できます。
Q. MySQLとPostgreSQLとSQL ServerでのLIMITの書き方の違いは?
A. MySQL/PostgreSQL: LIMIT 10 OFFSET 20。SQL Server: ORDER BY id OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY(ORDER BY必須)。Oracle(12c以降): FETCH FIRST 10 ROWS ONLYまたはOFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY
Q. LIMIT/OFFSETを使わずに特定の行を取得する方法はありますか?
A. ROW_NUMBER()ウィンドウ関数を使う方法があります:SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS rn FROM tbl) t WHERE rn BETWEEN 21 AND 30;。全RDBMSで動作し、複雑なソート条件でも対応できます。

まとめ

LIMIT句はSQLでデータの取得件数を制限するための重要な句です。この記事で学んだ内容を振り返りましょう。

目的 MySQL / PostgreSQL Oracle 12c+ SQL Server
先頭N件 LIMIT N FETCH FIRST N ROWS ONLY SELECT TOP N
M件スキップしてN件 LIMIT N OFFSET M OFFSET M ROWS FETCH NEXT N ROWS ONLY OFFSET M ROWS FETCH NEXT N ROWS ONLY
最新N件 ORDER BY 日付 DESC + 件数制限
ランキングTOP N ORDER BY 集計値 DESC + 件数制限
ページネーション OFFSET = (ページ番号 - 1) x 表示件数

この記事のポイント

  • LIMIT句でSELECTの取得件数を制限できる(MySQL / PostgreSQL)
  • ORDER BY + LIMITの組み合わせが実務の基本パターン
  • OFFSETを使うとページネーション(ページ送り)が実装できる
  • OracleとSQL ServerではFETCH FIRST / TOP / OFFSET-FETCHを使う
  • OFFSETが大きいとパフォーマンスが低下する → カーソルベース方式で対策
  • ORDER BYなしのLIMITは順序不定(再現性が必要なら必ずORDER BYを付ける)
  • OFFSETは0始まり(1件目から取得 = OFFSET 0)
  • 各グループからN件取得はROW_NUMBER() OVERを使う

LIMIT句はシンプルな構文ですが、ページネーションやパフォーマンスまで含めると奥が深い機能です。特にWebアプリケーション開発では、OFFSETの計算方法大量データでのカーソルベースページネーションは押さえておきたい重要なテクニックです。RDBMSごとの構文の違いも把握して、環境に合った書き方を選択してください。