SQLite | ゼロからはじめるSQL、30日で習得するSQLite:検索力強化 - Day9 件数制御

SQL SQLite
スポンサーリンク

Day9 後半

「どこから」「どれだけ」をコントロールして、結果を“切り分けて見る”

前半で、LIMIT を使って「最大何件まで取るか」をコントロールできるようになりました。
後半では、そこから一歩進んで

「何件目から取るか」
「ページごとに分けて取る(ページング)」
「LIMIT を付け忘れたときに何が起きるか」

といった、実務でめちゃくちゃよく出てくる視点を扱います。


LIMIT のもう一つの形「LIMIT オフセット, 件数」

「何件目から、何件取るか」を一文で指定する

SQLite では、LIMIT に2つの数値を渡す書き方ができます。

LIMIT オフセット, 件数;
SQL

ここでの「オフセット」は、「先頭から何件スキップするか」です。
0 なら「先頭から」、5 なら「先頭から5件飛ばして、6件目から」という意味になります。

たとえば、users テーブルがこうだとします。

id | name       | age
---+------------+----
 1 | 山田太郎   | 25
 2 | 佐藤花子   | 19
 3 | 鈴木一郎   | 30
 4 | 高橋健     | 22
 5 | 田中花子   | 28
 6 | 井上優     | 24
 7 | 森本亮     | 27

ここで、「年齢の高い順に並べたうえで、2件目から3件分だけ欲しい」とします。

まず、年齢の高い順に並べるとこうです。

SELECT * FROM users
ORDER BY age DESC;
SQL

結果(イメージ)はこうなります。

id | name       | age
---+------------+----
 3 | 鈴木一郎   | 30   ← 1件目
 5 | 田中花子   | 28   ← 2件目
 7 | 森本亮     | 27   ← 3件目
 1 | 山田太郎   | 25   ← 4件目
 6 | 井上優     | 24   ← 5件目
 4 | 高橋健     | 22   ← 6件目
 2 | 佐藤花子   | 19   ← 7件目

ここから「2件目から3件分」取りたいので、

オフセット:1(1件目を飛ばす)
件数:3

となります。

SELECT * FROM users
ORDER BY age DESC
LIMIT 1, 3;
SQL

結果はこうなります。

id | name       | age
---+------------+----
 5 | 田中花子   | 28   ← 2件目
 7 | 森本亮     | 27   ← 3件目
 1 | 山田太郎   | 25   ← 4件目

「どの順番で並べたうえで」「何件目から」「何件取るか」を、1本の SQL で指定できているのがポイントです。


ページングの入り口としての LIMIT

「1ページ10件」のような世界をSQLでどう表現するか

Webサービスでよく見る「1ページ10件表示」「次へ」「前へ」。
これを支えているのが、まさに LIMIT とオフセットの考え方です。

たとえば、「1ページ10件で、ページ番号は1から始まる」とします。

ページ1 → 先頭から10件
ページ2 → 11件目から10件
ページ3 → 21件目から10件

オフセットはこう計算できます。

ページNのオフセット = (N – 1) × 10

これを SQL に落とすと、たとえば「登録日の新しい順に、ページ2を表示したい」ならこうなります。

SELECT * FROM users
ORDER BY created_at DESC
LIMIT 10 OFFSET 10;
SQL

SQLite では

LIMIT 件数 OFFSET オフセット;
SQL

という書き方もできます(LIMIT オフセット, 件数 と同じ意味)。
どちらを使うかは好みですが、「件数」と「オフセット」が何を表しているかを意識できていればOKです。


LIMIT を付け忘れたときに起きること

「たまたま大丈夫」なうちに、怖さを知っておく

学習用の小さなテーブルだと、LIMIT を付けなくても特に問題は起きません。
しかし、実務のデータベースでは、テーブルに何十万件、何百万件と入っていることが普通です。

そこで、たとえばこう書いてしまうとします。

SELECT * FROM access_logs
ORDER BY created_at DESC;
SQL

本当は「上位100件だけ見たかった」のに、LIMIT を付け忘れたせいで、
全件を並び替えて返そうとします。

起きうることは、かなり重いです。

時間がかかる(最悪、他の処理を巻き込んで遅くなる)。
アプリケーションやブラウザが結果を受け止めきれずに固まる。
ログやネットワークに大量のデータが流れ、情報漏洩のリスクが上がる。

だからこそ、
「画面表示用の SELECT には、基本的に LIMIT を付ける」
「ログや監査用の画面でも、まずは LIMIT 付きで見る」
という設計は、性能とセキュリティの両方を守るための“お作法”です。


LIMIT と「確認のためのSELECT」の組み合わせ

「いきなり全部」ではなく「まず少しだけ見る」癖をつける

Day7 で、「UPDATE や DELETE の前に、同じ WHERE で SELECT して確認する」という話をしました。
その SELECT にも、LIMIT を組み合わせると、さらに安全度が上がります。

たとえば、こういう UPDATE をしたいとします。

UPDATE users
SET status = 'inactive'
WHERE last_login_at < '2024-01-01';
SQL

いきなり実行するのではなく、まずは

SELECT * FROM users
WHERE last_login_at < '2024-01-01'
ORDER BY last_login_at ASC
LIMIT 10;
SQL

のように、「対象になりそうな行の一部だけ」を確認します。

これで、「本当にこの条件で合っているか」「想定外のユーザーが含まれていないか」を、リスク少なくチェックできます。

「まず少しだけ見て、条件の妥当性を確かめる」
このときに LIMIT は、とても強力な“安全確認用の道具”になります。


小さな練習で締める

「ページNのSQL」を自分で組み立ててみる

頭の中で、次のような状況を SQL にしてみてください。

ユーザー一覧を、登録日の新しい順に1ページ20件で表示したい。
ページ3を表示するときの SQL は?

ヒントは、

並び順:ORDER BY created_at DESC
件数:20
ページ3 → オフセット = (3 – 1) × 20 = 40

です。

ここまでイメージできれば、あとは LIMITOFFSET を組み合わせるだけです。


Day9 後半のまとめ

LIMIT には「何件目から、何件取るか」を指定する形があり、ページングの基礎になる。
ORDER BY と組み合わせることで、「意味のある順番の一部だけ」を安全に取り出せる。
LIMIT を付け忘れると、性能面・セキュリティ面で大きなリスクになる。
UPDATE / DELETE 前の確認用 SELECT にも LIMIT を付け、「まず少しだけ見てから本番」という癖をつけると安全度が上がる。

ここまで来たあなたは、
「どの行を」「どの順番で」「どれだけ」
取り出すかを、かなり細かくコントロールできる状態です。
この土台の上に、次は集計(COUNT, SUM など)やグループ化(GROUP BY)を乗せていくと、検索力がさらに一段深くなっていきます。

タイトルとURLをコピーしました