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;
SQLSQLite では
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
です。
ここまでイメージできれば、あとは LIMIT と OFFSET を組み合わせるだけです。
Day9 後半のまとめ
LIMIT には「何件目から、何件取るか」を指定する形があり、ページングの基礎になる。ORDER BY と組み合わせることで、「意味のある順番の一部だけ」を安全に取り出せる。LIMIT を付け忘れると、性能面・セキュリティ面で大きなリスクになる。
UPDATE / DELETE 前の確認用 SELECT にも LIMIT を付け、「まず少しだけ見てから本番」という癖をつけると安全度が上がる。
ここまで来たあなたは、
「どの行を」「どの順番で」「どれだけ」
取り出すかを、かなり細かくコントロールできる状態です。
この土台の上に、次は集計(COUNT, SUM など)やグループ化(GROUP BY)を乗せていくと、検索力がさらに一段深くなっていきます。
