データベースを運用する上で、特定の期間に該当するレコードのみを抽出したい場面は非常に多く存在します。
売上の集計、ユーザーの行動ログの分析、特定期間のイベント情報の取得など、日付データを条件にしたクエリの作成はSQL操作の基本といえます。
本記事では、日付範囲を効率的かつ正確に指定するために欠かせないBETWEEN演算子の使い方について解説します。
基本的な構文から、実務で陥りやすい落とし穴、パフォーマンスへの影響、さらには代替手段との使い分けまで、詳しくご紹介します。
SQLのBETWEEN演算子とは
BETWEEN演算子は、特定の範囲内に値が含まれているかどうかを判定するための演算子です。
数値だけでなく、日付や文字列に対しても使用することが可能です。
日付に対して使用する場合、「開始日」から「終了日」までの範囲を指定してデータを抽出することができます。
BETWEEN演算子の最大の特徴は、指定した開始値と終了値の両方を含めるという点にあります。
これは数学的な表現で言うところの「以上、かつ、以下」に相当します。
BETWEEN演算子の基本構文
BETWEEN演算子の基本的な書き方は以下の通りです。
SELECT カラム名
FROM テーブル名
WHERE 日付カラム名 BETWEEN '開始日付' AND '終了日付';
この構文を使用することで、WHERE句で指定した範囲内のデータを直感的に取得できます。
比較演算子である >= (以上) と <= (以下) を組み合わせて書く場合と同じ結果を得られますが、BETWEENを使うことでコードの可読性が向上します。
日付範囲を指定する具体例
それでは、具体的なテーブルデータを用いてBETWEEN演算子の使い方を確認していきましょう。
以下のような orders (注文履歴) テーブルがあると仮定します。
| order_id | order_date | amount |
|---|---|---|
| 1 | 2026-01-01 | 5000 |
| 2 | 2026-01-15 | 3200 |
| 3 | 2026-01-31 | 1500 |
| 4 | 2026-02-01 | 8000 |
このテーブルから、2026年1月中の注文情報をすべて取得するクエリを記述します。
SELECT *
FROM orders
WHERE order_date BETWEEN '2026-01-01' AND '2026-01-31';
order_id | order_date | amount
---------+------------+-------
1 | 2026-01-01 | 5000
2 | 2026-01-15 | 3200
3 | 2026-01-31 | 1500
このように、2026-01-01 と 2026-01-31 のデータが両方含まれていることが分かります。
DATETIME型(日時)における注意点
日付を指定する際に最も注意しなければならないのが、時刻情報の有無です。
SQLのデータ型には、日付のみを保持する DATE 型と、日付と時刻を保持する DATETIME 型 (または TIMESTAMP 型) があります。
もしカラムのデータ型が DATETIME の場合、単に '2026-01-31' と記述すると、暗黙的に '2026-01-31 00:00:00' として扱われることが一般的です。
例えば、2026-01-31 15:30:00 に発生した注文データは、上記のBETWEEN句では抽出対象から漏れてしまいます。
なぜなら、終了値として指定した '2026-01-31 00:00:00' よりも後の時刻だからです。
時刻を含む場合の対策1:終了時刻を明示する
最もシンプルな解決策は、終了値にその日の最終時刻を指定することです。
SELECT *
FROM orders
WHERE order_date BETWEEN '2026-01-01 00:00:00' AND '2026-01-31 23:59:59';
これにより、1月31日の深夜までのデータを確実に取り込むことができます。
時刻を含む場合の対策2:比較演算子に切り替える
現場では、BETWEENを使わずに < (未満) を使った範囲指定を行うことも推奨されます。
SELECT *
FROM orders
WHERE order_date >= '2026-01-01' AND order_date < '2026-02-01';
この書き方であれば、1月31日の23時59分59秒であっても、2月1日の 00:00:00 未満であるため正しく抽出されます。
ミリ秒単位まで考慮が必要なモダンなデータベースシステムでは、こちらの「以上・未満」の形式がより安全とされています。
データベースごとの日付書式
SQLの標準規格はあるものの、日付の書き方や関数は使用するデータベース管理システム (DBMS) によって異なります。
代表的なデータベースでの扱いについて見ていきましょう。
MySQL / MariaDB
MySQLでは 'YYYY-MM-DD' 形式の文字列を日付として比較可能です。
また、現在の時刻を取得する NOW() 関数などを組み合わせて使用することも多いです。
PostgreSQL
PostgreSQLは型に対して厳格ですが、文字列から日付への自動キャスト機能が強力です。
明示的にキャストを行う場合は '2026-01-01'::date のような記述を用います。
SQL Server (T-SQL)
SQL Serverでは、日付文字列の解釈がロケール設定に依存することがあります。
混乱を避けるために 'YYYYMMDD' (ハイフンなし) というISO形式を使用することが安全策として推奨されています。
BETWEENを使った便利なテクニック
日付範囲の指定は、固定値だけでなく動的な値と組み合わせることでさらに強力になります。
過去7日間のデータを取得する
現在の日時を基準にして、過去一週間のデータを抽出したいケースです。
MySQLを例に挙げると、以下のように記述できます。
SELECT *
FROM orders
WHERE order_date BETWEEN DATE_SUB(NOW(), INTERVAL 7 DAY) AND NOW();
このクエリにより、常に最新の1週間分のデータがレポートに表示されるようになります。
NOT BETWEEN による範囲外の抽出
「特定の期間を除外したい」という場合は、NOT BETWEEN を使用します。
SELECT *
FROM events
WHERE event_date NOT BETWEEN '2026-04-29' AND '2026-05-06';
これにより、ゴールデンウィーク期間中以外のイベントをリストアップするといった操作が可能です。
パフォーマンスとインデックスへの影響
大量のデータを扱う際、検索条件に指定するカラムにインデックスが貼られているかどうかは非常に重要です。
BETWEEN演算子は、基本的にインデックスが有効に活用される検索方法です。
B-Treeインデックスが作成されていれば、範囲検索として高速に処理されます。
ただし、日付カラムに対して関数を適用してしまうと、インデックスが効かなくなるため注意が必要です。
例えば、以下の書き方は非推奨です。
-- インデックスが使われない可能性がある悪い例
SELECT * FROM orders WHERE DATE_FORMAT(order_date, '%Y-%m') = '2026-01';
日付の「月」だけで判定したい場合でも、カラム自体を加工するのではなく、BETWEENで範囲(’2026-01-01′ から ‘2026-01-31’)を指定する方がパフォーマンスに優れています。
よくある間違いとトラブルシューティング
SQLのBETWEENで日付を扱う際に初心者が陥りやすいミスをまとめました。
開始日と終了日の逆転
BETWEEN 演算子では、必ず 開始値 AND 終了値 の順で指定する必要があります。
-- 何もヒットしない例
WHERE order_date BETWEEN '2026-12-31' AND '2026-01-01';
値が逆転していると、構文エラーにはなりませんが、結果が0件となってしまいます。
タイムゾーンの影響
サーバーのタイムゾーン設定と、保存されているデータのタイムゾーンが異なる場合、意図した範囲がずれることがあります。
特にクラウド上のデータベースを使用している場合、UTC (協定世界時) で保存されていることが多いため、日本時間 (JST) との9時間の差を考慮してクエリを書かなければなりません。
型が一致していない
文字列型 (VARCHAR) で保存された日付データをBETWEENで比較すると、辞書順での比較になってしまいます。
その結果、日付としての正しい前後関係で判定されないリスクがあります。
日付データは必ず DATE や TIMESTAMP といった適切な型で保存し、必要に応じて CAST 関数を使用して型変換を行ってください。
まとめ
SQLのBETWEEN演算子は、日付範囲を指定してデータを抽出する際に非常に便利で直感的な手段です。
「開始値と終了値の両方を含む」という特性を理解し、特に時刻情報を含む DATETIME 型を扱う際には、境界値の定義に注意を払いましょう。
より厳密な制御が必要なシステムでは、比較演算子 >= や < を使った範囲指定を検討するのも一つの手です。
また、クエリの実行効率を下げないよう、日付カラムにインデックスを適用し、カラムに関数を通さないように意識することがプロフェッショナルなSQL作成への近道です。
今回解説したポイントを押さえて、正確で効率的なデータ抽出を実践してみてください。
