MySQL 入門

MySQL LIMIT 句

これまでに、特定のカラムを選択する方法、WHERE 句による行のフィルタリング、そして ORDER BY を使った結果のソートについて学習しました。では、リスト全体ではなく、結果の特定の一部だけが必要な場合はどうすればよいでしょうか?ここで LIMIT 句が登場します。これはクエリが返す行数を制限するために使用され、ページネーション、Top N(上位N個)レポート、あるいは単なるデータのサンプリングを実装する際に非常に便利です。

1. 基本的な LIMIT の使い方

LIMIT の最もシンプルな使い方は、一つの整数値を指定することです。これにより、MySQLは SELECT ステートメント、および WHEREORDER BY 句にマッチした結果の先頭から、指定した行数だけを正確に返すようになります。

句の順序が重要であることを覚えておいてください。LIMIT はほとんどの場合、SELECT ステートメントの最後に配置されます。

SELECT column1, column2
FROM your_table
WHERE condition
ORDER BY column1 DESC
LIMIT N; -- Nは取得する最大行数

world データベースの city(都市)テーブルを使用した例を見てみましょう。人口が最も多い5つの都市を確認したいとします。

SELECT Name, CountryCode, Population
FROM city
ORDER BY Population DESC
LIMIT 5;

このクエリは、まずすべての都市を人口の降順でソートし、最も大きい都市を先頭に並べます。その後、LIMIT 5 によってそのソート済みリストから上位5つの都市のみを抽出します。

NameCountryCodePopulation
SeoulKOR9,981,619
MumbaiIND10,500,000
ShanghaiCHN9,696,300
Mexico CityMEX8,591,309
JakartaIDN9,604,919

2. LIMIT と OFFSET:データページネーションの実装

通常、単に上位 N 個の結果が欲しいだけでなく、その「次の N 個」の結果、あるいは特定の「ページ」の結果が必要になることがあります。ここで LIMITOFFSET の組み合わせが活躍します。OFFSET 値は、結果を返し始める前に何行スキップするかを MySQL に指示します。

構文は LIMIT N OFFSET M で、N は取得する行数、M はスキップする行数です。

SELECT column1, column2
FROM your_table
WHERE condition
ORDER BY column1 ASC
LIMIT N OFFSET M; -- M行スキップした後、N行を返す

また、短縮形として LIMIT M, N を使用することもできます。これは「M 行スキップし、その後 N 行を返す」という意味になります。

SELECT column1, column2
FROM your_table
WHERE condition
ORDER BY column1 ASC
LIMIT M, N; -- M行スキップし、N行を返す

LIMIT N OFFSET MLIMIT M, N はどちらも同じ結果をもたらします。自分がより読みやすいと感じる方を選択してください。多くのデベロッパーは、慣れてくると簡潔な LIMIT M, N を好んで使用します。

再び city テーブルでデモンストレーションします。すでに人口上位 5 位までの都市は見つけました。次は、その次の 5 つの都市(つまり人口ランキング 6 位から 10 位の都市)を探してみましょう。

SELECT Name, CountryCode, Population
FROM city
ORDER BY Population DESC
LIMIT 5 OFFSET 5; -- 先頭の5行をスキップし、次の5行を返す

あるいは短縮形を使用します:

SELECT Name, CountryCode, Population
FROM city
ORDER BY Population DESC
LIMIT 5, 5; -- 5行スキップし、5行返す

これらのクエリは、以下のような出力を生成します。

NameCountryCodePopulation
DelhiIND9,817,439
KarachiPAK9,269,265
TokyoJPN7,980,230
BeijingCHN7,472,000
New YorkUSA8,008,278

このパターンは Web アプリケーションにおけるページネーション実装の基礎であり、ユーザーが巨大なデータセットを 1 ページずつブラウズすることを可能にします。

3. 重要な注意事項

3.1 ORDER BY と LIMIT の併用は不可欠

ORDER BY 句なしで LIMIT を使用した場合、返される結果の順序は一切保証されません。MySQL はその時々で最も効率的だと判断した順序で行を返す可能性があります。一貫性があり予測可能なデータのサブセット(「トップ10」や「次のページ」など)が必要な場合は、LIMIT を適用する前に ORDER BY を使用して明確なソート規則を確立しなければなりません。

3.2 大きなオフセットによるパフォーマンス問題

OFFSET を伴う LIMIT はページネーションに最適ですが、極端に大きなオフセット値によるパフォーマンスへの影響には注意が必要です。例えば、LIMIT 10 OFFSET 1000000 は、MySQL が依然として最初の 1,000,010 行をスキャンして識別し、そのうちの先頭 1,000,000 行を破棄してから、残りの 10 行を返すことを意味します。非常に大きなテーブルでは、この処理は非常に低速になる可能性があります。極端なディープページネーション(深い階層のページ表示)には、通常よりパフォーマンスの高い代替戦略(「キーセット・ページネーション(keyset pagination)」や、インデックス列に対する WHERE 句を利用した「シーク法(seek method)」など)が存在しますが、これらは今後の高度なトピックとなります。一般的な日常のユースケースであれば、LIMITOFFSET で全く問題ありません。

3.3 クエリの実行順序

MySQL が LIMITOFFSET を含む SELECT ステートメントを処理する際、通常以下の順序で操作が行われます。

  1. FROM 句: テーブルの特定
  2. WHERE 句: 行のフィルタリング
  3. GROUP BY 句: 行のグループ化・集約(存在する場合)
  4. HAVING 句: 集約後のグループのフィルタリング(存在する場合)
  5. SELECT 句: 出力するカラムと式の確定
  6. ORDER BY 句: 結果行のソート
  7. LIMIT/OFFSET 句: ソートされた行のサブセットの選択

この実行フローが示すように、LIMIT/OFFSET はすべてのフィルタリング、グループ化、ソートが完了した後の最終段階で適用されます。