PostgreSQLで日付フィルタを書くときに気をつけていること

こんにちは、さるまりんです 🐒

以前、前月分のデータを集計する記事を書きました。

今回は少し視点を変えて、

日付フィルタを書くときに、僕が気をつけていること

をまとめてみます。

日付フィルタは本当によく書きます。
だからこそ「毎回迷わない形」を持っておくと、あとで自分を助けてくれます。

前月の範囲を取得する基本

まずは前月の境界から。

今月の月初

DATE_TRUNC('month', CURRENT_DATE)

たとえば 2026年2月中なら、

2026-02-01 00:00:00

が返ります。

前月の開始

DATE_TRUNC('month', CURRENT_DATE) - INTERVAL '1 month'

2026-01-01 00:00:00

前月の終了はどう考える?

ここがポイントです。

前月末「以下」にするのではなく、

今月の月初「未満」にする

と考えます。

BETWEENは便利。でも少し危険

よく見る書き方:

WHERE order_date BETWEEN start AND end

一見わかりやすいです。

でも TIMESTAMP 型の場合、

2026-01-31 23:59:59.999

のようなデータが存在します。

秒だけでなく、ミリ秒、マイクロ秒まであります。

境界を「以下」にすると、
このあたりで思わぬズレが起きることがあります。

実際、僕は一度これで売上が微妙に合わず、冷や汗をかきました。

僕がよく使う書き方(未満パターン)

WHERE order_date >= DATE_TRUNC('month', CURRENT_DATE) - INTERVAL '1 month'
AND order_date < DATE_TRUNC('month', CURRENT_DATE)

上限は「未満」にする。 これで、

  • ミリ秒
  • マイクロ秒

を意識せずに済みます。 境界をまたぐ心配がなくなるのです。

なぜ「未満」が安全なのか?

ポイントはこれです。

境界値を含めるかどうかで悩まなくてよくなる

「前月末 23:59:59.999 まで」と考えるより、 「今月の月初 未満」と考えるほうが 圧倒的にミスが減ります。

列に関数をかけない これもかなり大事です。

悪い例

WHERE DATE_TRUNC('month', order_date) = DATE_TRUNC('month', CURRENT_DATE) - INTERVAL '1 month'

これだと、order_date にインデックスを貼っていても効きません。 なぜなら、列に関数をかけているからです。

良い例

WHERE order_date >= ...
AND order_date < ...

列はそのまま。 動かすのは「値側」です。 これだけで、パフォーマンスは大きく変わります。

よく使うパターン集

実務でよく書くものを並べておきます。

今日

WHERE created_at >= CURRENT_DATE
AND created_at < CURRENT_DATE + INTERVAL '1 day'

昨日

WHERE created_at >= CURRENT_DATE - INTERVAL '1 day'
AND created_at < CURRENT_DATE

今月

WHERE created_at >= DATE_TRUNC('month', CURRENT_DATE)
AND created_at < DATE_TRUNC('month', CURRENT_DATE) + INTERVAL '1 month'

今年

WHERE created_at >= DATE_TRUNC('year', CURRENT_DATE)
AND created_at < DATE_TRUNC('year', CURRENT_DATE) + INTERVAL '1 year'

直近7日(今この瞬間まで)

WHERE created_at >= NOW() - INTERVAL '7 days'

用途によっては、

WHERE created_at >= CURRENT_DATE - INTERVAL '7 days'
AND created_at < CURRENT_DATE + INTERVAL '1 day'

のように「日単位」で切ることもあります。

僕の中でのルールまとめ

  • BETWEENは便利。でも境界に注意
  • 上限は「未満」が安全
  • 列に関数をかけない
  • 値側を動かす
  • 毎回同じ形で書く

日付フィルタは、本当に何度も出てきます。

だからこそ、

書き方を決めておく

これが一番の時短になります。

おわりに

データベースは、データの専門家です。

でも、どう使うか、どう切り出すかは書き手の責任です。

僕は
境界を丁寧に扱うだけで、
安心感がかなり変わりました。

また今日も新しいデータと向き合うかもしれません。

そのとき、少しでも楽になりますように。

読んでくださってありがとうございました。

それではまた! 🐒🔧