【PostgreSQL】期間指定の書き方をわかりやすく解説

※ この記事にはアフィリエイトリンクが含まれます

期間指定のSQLでうまく絞り込みができずに悩んでいませんか?

・日付の境界(開始・終了)が正しく扱えず漏れが出ることがある。

・時間帯(タイムゾーン)やタイムスタンプ型の違いで結果が変わることがある。

・インデックスが効かず、クエリが遅くなることがある。

結論から言うと、期間指定は型の理解と境界の扱い、インデックスを意識すれば正確で高速になります。

・日付/時刻型を意識して BETWEEN か比較演算子を使う。

・タイムゾーンや時刻を考慮して変換(AT TIME ZONE)やトランケート(date_trunc)を使う。

・インデックスが効く書き方(直接カラム比較や関数インデックス)を検討する。

この記事では、PostgreSQLでの期間指定SQLの基本から実践的な書き方、よくある落とし穴とパフォーマンス対策までを初心者にもわかりやすく解説します。

目次

期間指定の基本的な考え方

まずは期間指定で何を比較するかをはっきりさせましょう。

主に扱う型は datetimestamptimestamp with time zone の三つです。

date は日付のみで時間がありません。timestamp はタイムゾーン情報を持たない日時、timestamp with time zone はタイムゾーンを含みます。

日付型とタイムスタンプ型の違い

date 型は “2026-03-24” のように日付だけを扱います。

一方で timestamp は時刻も扱うため、期間の開始・終了で時間まで考慮する必要があります。

timestamp with time zone(略して timestamptz)は内部的にUTCで管理され、表示時にセッションのタイムゾーンへ変換されます。

よく使う期間指定の書き方

よく使われる方法は主に三つです。BETWEEN、比較演算子、日付関数を使う方法です。

まずは基本的なサンプルを見ておきましょう。テーブル名は events、日時カラムは event_time とします。

SELECT * FROM events
WHERE event_time BETWEEN '2026-03-01' AND '2026-03-31';

この書き方は直感的ですが、timestamp 型だと終了日の 2026-03-31 00:00:00 までしか含みません。

そのため、日付の終端を含めたい場合は終了日を翌日0時の直前にする、あるいは比較演算子を使って調整します。

-- 終了日の23:59:59を指定するのは誤差を生むことがある
SELECT * FROM events
WHERE event_time >= '2026-03-01'
  AND event_time < '2026-04-01';

この書き方(開始を >=、終了を < で翌日を指定)は、時間を含むカラムに対して安全で一般的です。

日付だけで絞る場合

カラムが date 型の場合は BETWEEN で直感的に扱えます。

SELECT * FROM events
WHERE event_date BETWEEN '2026-03-01' AND '2026-03-31';

しかし timestamp 型で日付単位で抽出したい場合は、date_trunc や CAST を使う方法があります。

SELECT * FROM events
WHERE event_time::date BETWEEN '2026-03-01' AND '2026-03-31';

ただし event_time::date のように関数をWHERE側で直接使うとインデックスが効かない場合があります。

日付の境界(開始/終了)を正しく扱う

期間指定で最もミスが起きやすいのが境界の扱いです。

特に timestamp を扱う場合、終了日を含めたいのか含めたくないのかを明確にする必要があります。

推奨される方法は終了を次の日の開始未満(<)で指定する方法です。

-- 2026-03-01 から 2026-03-31 までを含めたい場合
SELECT * FROM events
WHERE event_time >= '2026-03-01'
  AND event_time < '2026-04-01';

この方法なら時間を気にせず、漏れや重複を防げます。

夜跨ぎや夏時間(DST)の考慮

タイムゾーンや夏時間が関係する環境では、単純な文字列比較で誤差が出ることがあります。

その場合は timestamptz を使い、適切に AT TIME ZONE で変換してから比較すると安全です。

-- ローカルタイムをUTCに変換して比較する例
SELECT * FROM events
WHERE event_time AT TIME ZONE 'Asia/Tokyo' >= '2026-03-01 00:00:00'
  AND event_time AT TIME ZONE 'Asia/Tokyo' <  '2026-04-01 00:00:00';

パフォーマンスを考えた書き方とインデックス

期間指定でよくある問題はインデックスが効かず遅くなることです。

関数を直接WHERE句で使うと通常のインデックスは使えません。

例えば WHERE event_time::date = '2026-03-01' はインデックスを無効化します。

インデックスを活かすテクニック

直接カラムに対する比較(event_time >= ... AND event_time < ...)はシンプルでインデックスを活かせます。

もし日付単位でよく検索するなら、日付だけのカラムを追加してインデックスを張るか、関数インデックスを作成します。

-- 日付カラムを追加する案
ALTER TABLE events ADD COLUMN event_date date;
UPDATE events SET event_date = event_time::date;
CREATE INDEX idx_events_event_date ON events (event_date);

-- 関数インデックスの例
CREATE INDEX idx_events_date_trunc ON events (date_trunc('day', event_time));

関数インデックスを使えば WHERE date_trunc('day', event_time) = '2026-03-01' のような書き方でもインデックスが効きます。

よくある実用的なケースとSQL例

ここでは日常的によく使う期間指定のパターンと具体例を示します。

過去N日分を抽出する

直近7日などを抽出する際は interval を使うと便利です。

SELECT * FROM events
WHERE event_time >= now() - interval '7 days';

この方法は現在時刻から相対的に抽出できるため、バッチ処理などで便利です。

月単位で抽出する(指定月の全件)

特定の月の全データを取りたいときは月の最初と次月の開始未満で指定します。

SELECT * FROM events
WHERE event_time >= date_trunc('month', DATE '2026-03-01')
  AND event_time <  date_trunc('month', DATE '2026-03-01') + interval '1 month';

週単位で抽出する

週の定義(何曜日を開始とするか)によって書き方が変わりますが、date_trunc('week', ...) が使えます。

SELECT * FROM events
WHERE event_time >= date_trunc('week', now())
  AND event_time <  date_trunc('week', now()) + interval '1 week';

複雑な期間(営業日やカレンダーに依存)

営業日ベースの抽出など、単純な日付範囲で済まない場合はカレンダーテーブルを用意すると良いです。

カレンダーテーブルとJOINすれば、休業日除外や任意のルールで抽出できます。

安全性とパラメータ化の推奨

ユーザー入力で期間を受け取る場合は必ずパラメータ化してSQLインジェクションを防ぎましょう。

プレースホルダを使うことでDBドライバが適切に型変換してくれます。

-- 例: Python の psycopg2 の場合
cur.execute(
  "SELECT * FROM events WHERE event_time >= %s AND event_time < %s",
  (start_datetime, end_datetime)
)

まとめ:正確で高速な期間指定のポイント

期間指定を正しく行うためのポイントは三つです。

1. カラムの型を理解して境界(含める/含めない)を明確にすること。

2. タイムゾーンや夏時間に注意して必要なら AT TIME ZONE を使うこと。

3. インデックスが効く書き方(直接比較、関数インデックス、日付カラム追加)を検討すること。

これらを押さえれば、誤差の少ない正確な抽出と性能面の両方を両立できます。

この記事で紹介したサンプルを元に、実際のデータや要件に合わせて調整してみてください。

必要であれば、具体的なテーブル定義やクエリを提供いただければ、より適切なアドバイスを差し上げます。


postgreSQLは、現場でも広く使われている信頼性の高いデータベースです。もしこれから本格的に学び、実務で通用する力をつけたい方には、RareTECHをチェックしてみてください。実案件ベースのカリキュラムで、あなたのスキルを次のステージへ引き上げてくれるはずです。

なんくる

「本当にエンジニアとしてやっていけるか不安…」という方も、実践的な開発に関わることで、転職後の働き方を事前に体感できますよ。

実務で使えるDBスキルとともに、プログラミングスキルをちゃんと身につけたいなら、
RareTECH無料カウンセリングで、学ぶ目的やゴールをプロと一緒に明確にしてみましょう。独学では得られない「実践的な成長の道筋」が見えてきます。


もしこの内容を通して、PostgreSQLについてさらに理解を深めたいと感じられたなら、信頼できる講座や書籍を紹介した別記事をご覧いただくのも良いかと思います。ご自身の学びに、きっとお役立ていただけるはずです。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

沖縄出身のエンジニアです。IT業界で5年以上の経験があり、主にC#やPHPを使って開発を行ってきました。新しい技術にも興味があり、日々学びながらスキルアップを目指しています。

コメント

コメントする

CAPTCHA


目次