SQL(Structured Query Language)を用いたデータ操作において、特定の範囲内に収まるレコードを抽出する作業は頻繁に発生します。
例えば、商品の価格帯で検索したり、特定の期間内に発生した売上データを集計したりする場合、数値や日付の「範囲」を指定する必要があります。
このような場面で非常に役立つのが、SQLのBETWEEN演算子です。
BETWEEN演算子を正しく使いこなすことで、クエリの可読性が大幅に向上し、メンテナンスのしやすいコードを記述できるようになります。
本記事では、BETWEEN演算子の基本的な書き方から、データ型ごとの具体的な活用例、そして実務でハマりやすい注意点までを詳しく解説します。
SQLのBETWEEN演算子とは?
BETWEEN演算子は、WHERE句で使用される比較演算子の一つで、指定した範囲内に値が含まれているかどうかを判定します。
もっとも大きな特徴は、指定した「開始値」と「終了値」の両方を含む(境界値を含む)という点にあります。
数学的な表現を用いるならば、「開始値 ≦ 対象の値 ≦ 終了値」という条件を一つのキーワードで表現できる仕組みです。
従来の比較演算子である >=(以上)や <=(以下)を組み合わせて記述することも可能ですが、BETWEENを使う方が直感的でスッキリとした記述になります。
データベースの種類(MySQL、PostgreSQL、Oracle、SQL Serverなど)を問わず、標準的なSQLとして広くサポートされています。
BETWEEN演算子の基本構文
まずはBETWEEN演算子の基本的な書き方を確認しましょう。
SELECT カラム名
FROM テーブル名
WHERE カラム名 BETWEEN 開始値 AND 終了値;
この構文において、AND は開始値と終了値を区切るために必須のキーワードとなります。
ここで重要なのは、必ず「開始値」には小さい値を、「終了値」には大きい値を記述しなければならないという点です。
多くのデータベースエンジンにおいて、この順番を逆に(大きい値 BETWEEN 小さい値)記述すると、エラーにはなりませんが、結果が1件も取得できない状態になります。
これは、内部的に (カラム >= 開始値) AND (カラム <= 終了値) という論理演算が行われているためです。
数値データでのBETWEEN活用例
BETWEEN演算子が最も直感的に利用されるのは、数値型のデータを扱うシーンです。
例えば、ECサイトのデータベースから「価格が3,000円から7,000円の商品」を抽出する場合を考えてみましょう。
-- productsテーブルから価格が3000円以上7000円以下の商品を抽出する
SELECT product_name, price
FROM products
WHERE price BETWEEN 3000 AND 7000;
| product_name | price |
|--------------|-------|
| キーボード | 3500 |
| マウス | 3000 |
| モニター | 7000 |
出力結果からも分かる通り、3000ちょうどや7000ちょうどの値も含まれている点に注目してください。
もし境界値を含めたくない場合は、BETWEENではなく > や < を使用する必要があります。
日付データでのBETWEEN活用例
日付や時刻の範囲指定においても、BETWEEN演算子は非常に強力なツールとなります。
日報の出力や、特定月の売上集計など、実務での利用頻度は数値データ以上かもしれません。
例えば、2026年1月の1ヶ月間に行われた注文データを抽出するクエリは以下のようになります。
-- ordersテーブルから2026年1月中の注文を抽出する
SELECT order_id, order_date
FROM orders
WHERE order_date BETWEEN '2026-01-01' AND '2026-01-31';
| order_id | order_date |
|----------|------------|
| 101 | 2026-01-01 |
| 102 | 2026-01-15 |
| 103 | 2026-01-31 |
ただし、日付データを扱う際には「時刻」の扱いに注意が必要です。
データ型が DATE 型(日付のみ)であれば問題ありませんが、DATETIME や TIMESTAMP 型(日時)の場合、'2026-01-31' は内部的に '2026-01-31 00:00:00' と解釈されることが多いです。
その場合、1月31日の正午に発生したデータなどは「終了値よりも大きい」と判断され、抽出漏れが発生するリスクがあります。
このような事態を避けるためには、終了値を '2026-01-31 23:59:59' と指定するか、日付をキャスト(型変換)する工夫が求められます。
文字列データでのBETWEEN活用例
あまり知られていない活用法として、文字列データに対する範囲指定があります。
文字列の場合、辞書順(アルファベット順や文字コード順)に基づいて範囲が判定されます。
-- employeesテーブルから名前が「A」から「C」で始まる社員を抽出する
SELECT employee_name
FROM employees
WHERE employee_name BETWEEN 'A' AND 'C';
このクエリを実行すると、「Adams」や「Brown」といった名前はヒットしますが、「Charles」は注意が必要です。
もし名前が「C」そのものであれば含まれますが、「Ca…」のように「C」の後に文字が続く場合、それは辞書順で「C」よりも後ろにあると判定されます。
したがって、「C」で始まる全ての名前を含めたい場合は、終了値を 'C' ではなく 'D' 未満とするか、ワイルドカードを検討する方が確実な場合もあります。
NOT BETWEENによる範囲外の指定
BETWEEN演算子の前に NOT を付与することで、「範囲に含まれないデータ」を抽出することが可能です。
これは、特定の期間を除外したり、異常値(極端に安い、あるいは高い価格帯)を調査したりする際に便利です。
-- 価格が1000円から10000円「以外」の商品を抽出する
SELECT product_name, price
FROM products
WHERE price NOT BETWEEN 1000 AND 10000;
この場合、999円以下の商品と、10001円以上の商品が結果として返されます。
論理的には (price < 1000) OR (price > 10000) と同じ意味になりますが、NOT BETWEENを用いる方が直感的に条件を理解できるでしょう。
BETWEEN演算子を使用する際の重要な注意点
BETWEEN演算子は便利ですが、エンジニアが陥りやすい罠がいくつか存在します。
予期せぬバグを生まないために、以下の3つのポイントを必ず押さえておきましょう。
1. 境界値の扱い(Inclusive)
繰り返しになりますが、BETWEENは「開始値」と「終了値」を両方含みます。
「10歳から20歳未満」という条件を書きたい時に BETWEEN 10 AND 20 と書くと、20歳が含まれてしまうため間違いです。
この場合は、age >= 10 AND age < 20 と記述するのが正解です。
2. NULL値の扱い
SQLにおいて NULL は「不明」を意味する特殊な値です。
もし比較対象のカラムに NULL が含まれている場合、そのレコードはBETWEENの条件に一致しません(範囲内とも範囲外とも判定されず、結果から除外されます)。
また、開始値や終了値に NULL を指定した場合も、結果は常に空(不明)となります。
NULL を含むデータを考慮する必要がある場合は、IS NULL などの条件を併用するようにしましょう。
3. 引数の順序
BETWEEN 100 AND 50 のように、開始値に大きい値を、終了値に小さい値を設定すると、通常のSQLでは「常に偽(false)」とみなされます。
プログラミング言語によっては柔軟に解釈してくれるものもありますが、標準SQLでは「100以上 かつ 50以下」という矛盾した条件になるためです。
動的にクエリを生成する場合は、渡される変数の大小関係を事前にチェックするか、LEAST 関数や GREATEST 関数を用いて値を整理する必要があります。
BETWEENと代替構文の比較(パフォーマンス面)
「BETWEENを使うのと、比較演算子をANDで繋ぐのではどちらが速いのか?」という疑問を持つ方もいるでしょう。
結論から申し上げますと、現代の主要なデータベース(MySQL, PostgreSQL等)において、両者の実行速度に違いはありません。
データベース内部のオプティマイザ(実行計画を立てるエンジン)が、BETWEENを比較演算子の組み合わせに自動的に変換して処理するためです。
| 要件 | 比較演算子(AND) | BETWEEN演算子 |
|---|---|---|
| 可読性 | 普通(条件が増えると複雑) | 高い(簡潔に記述可能) |
| 境界値の指定 | 自由(未満、以下を選択可) | 固定(必ず「以下」になる) |
| 実行速度 | 高速(インデックス利用可) | 高速(インデックス利用可) |
| 記述量 | 多い(カラム名を2回書く) | 少ない(カラム名は1回) |
パフォーマンスが同じであれば、読みやすさと書きやすさに優れるBETWEEN演算子を優先的に利用するのが、良いSQLを書くためのプラクティスと言えます。
実務で役立つTips:動的な範囲指定
Webアプリケーションなどでユーザーが入力した値をもとに範囲検索を行う場合、値が入力されていない(空文字やNULL)ケースを考慮する必要があります。
単純にBETWEENに値を当てはめるだけでは、入力がない場合にエラーになるか、全てのデータが除外されてしまいます。
-- 動的な検索のイメージ(疑似コード)
SELECT * FROM sales
WHERE (price BETWEEN :min_price AND :max_price)
OR (:min_price IS NULL AND :max_price IS NULL);
このように、入力値がNULLの場合は条件をスルーするようなロジックを WHERE 句に組み込むことで、柔軟な検索機能を実装できます。
まとめ
SQLのBETWEEN演算子は、数値、日付、文字列などのデータを範囲指定で効率的に抽出するための非常に便利な機能です。
「開始値と終了値をともに含む」という仕様を正しく理解し、特に日付データやNULL値の扱いに注意を払うことで、正確なデータ抽出が可能になります。
可読性の高いクエリは、チーム開発におけるレビューの負担を減らし、将来的なメンテナンスコストの削減にも繋がります。
比較演算子 >= と <= を多用している箇所があれば、ぜひこの機会にBETWEEN演算子への書き換えを検討してみてください。
基礎をしっかりとマスターして、より洗練されたSQLを書けるようになりましょう。
