行数の制限/ページング(LIMIT/OFFSET、FETCH、ROWNUM、TOP)
Oracle
-- 12c+ standard: OFFSET/FETCH
SELECT name, salary FROM employee
ORDER BY salary DESC
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
-- Older versions: with ROWNUM
SELECT * FROM (
SELECT name, salary FROM employee ORDER BY salary DESC
) WHERE ROWNUM <= 10;結果セットの制限/ページングに使用する。Oracle 12c 以降は標準の OFFSET n ROWS FETCH NEXT m ROWS ONLY がサポートされる。それ以前は ROWNUM 疑似列を使用していた。ROWNUM はソート前に割り当てられるため、ORDER BY のサブクエリで囲む必要がある。
PostgreSQL
-- LIMIT/OFFSET
SELECT name, salary FROM employee
ORDER BY salary DESC
LIMIT 10 OFFSET 20;
-- Standard equivalent: FETCH
SELECT name, salary FROM employee
ORDER BY salary DESC
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;PostgreSQL は LIMIT n OFFSET m と標準の OFFSET ... FETCH 形式の両方をサポートする。大きな OFFSET 値は遅い。深いページングにはキーベース(keyset / 'WHERE id > last_id')のページネーションのほうが効率的。ORDER BY のない LIMIT は結果の順序を保証しない。
MySQL
-- LIMIT [offset,] row_count
SELECT name, salary FROM employee
ORDER BY salary DESC
LIMIT 10 OFFSET 20;
-- Short form: LIMIT offset, row_count
SELECT name, salary FROM employee ORDER BY salary DESC LIMIT 20, 10;MySQL/MariaDB は LIMIT キーワードを 2 つの形式で使用する: LIMIT row_count OFFSET offset または LIMIT offset, row_count。MySQL 8.0.19+ は標準の FETCH 構文も受け付ける。深い OFFSET の性能対策には keyset ページネーションが推奨される。
SQL Server
-- First N with TOP
SELECT TOP 10 name, salary FROM employee ORDER BY salary DESC;
-- OFFSET/FETCH for paging (2012+), ORDER BY mandatory
SELECT name, salary FROM employee
ORDER BY salary DESC
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;SQL Server は先頭 N 行に TOP n(TOP (n) PERCENT / WITH TIES の変形あり)を、2012 以降のページングに OFFSET ... FETCH を使用する。OFFSET/FETCH が動作するには ORDER BY が必須。SQL Server には LIMIT キーワードはない。
MongoDB
// Paging with skip/limit
db.employee.find()
.sort({ salary: -1 })
.skip(20)
.limit(10)MongoDB では limit() が返すドキュメント数を、skip() がスキップする数を設定し、sort() と組み合わせてページングを行う。大きな skip 値は高コスト。深いページングには、最後に見た値に基づく範囲(keyset)クエリが推奨される。
Redis
# Range read on a sorted set (ZSET):
ZREVRANGE salary_sorted 20 29 # members ranked 21-30
# Range on a list:
LRANGE queue 0 9 # first 10 elementsRedis には SQL の LIMIT はないが、範囲読み取りのコマンドがある: Sorted Set には ZRANGE/ZREVRANGE start stop(インデックスベース)または ZRANGEBYSCORE ... LIMIT offset count、List には LRANGE。これらのコマンドでページングのようなアクセスができる。
Elasticsearch
GET employee/_search
{
"from": 20,
"size": 10,
"sort": [ { "salary": "desc" } ]
}Elasticsearch では 'size' が返すヒット数を、'from' がスキップする数を設定する(LIMIT/OFFSET に相当)。from+size は最大 index.max_result_window(デフォルト 10,000)まで。深いページングには 'search_after'(keyset)または PIT(point-in-time)を使用する。