※ この記事にはアフィリエイトリンクが含まれます
PostgreSQLで月初や月末の日付を取得する方法に悩んでいませんか?
日付関連の処理は業務システムでよく使われますが、意外とつまずくポイントが多いです。
- 指定した日付から正しく月初・月末を計算できない
- タイムゾーンや時刻型によって結果がずれる
- パフォーマンスを考えた書き方がわからない
結論から言うと、PostgreSQLでは組み込み関数を組み合わせることで簡潔かつ高性能に月初・月末を取得できます。
基本はdate_truncとinterval、もしくはdate型のキャストを活用することです。
date_trunc('month', 日付)で月初(時刻は0:00)を取得- 月初に1か月足して1日引くことで月末を取得
to_charやextractでフォーマットや集計に対応
この記事では、初心者向けに基礎知識と代表的なSQL例、よくあるパターン別の実装法、パフォーマンス改善のコツまで実用的に解説します。
読み終えると業務で使えるクエリがすぐ書けるようになります。
PostgreSQLで日付を扱う基本
まずは日付・時刻型の基本を押さえましょう。
PostgreSQLにはdate、timestamp、timestamptzなどの型があります。
dateは日付のみを扱い、timestampは時刻情報を含みます。
timestamptzはタイムゾーン情報を考慮したtimestampです。
多くの月初・月末処理はdate型で行うとシンプルです。
ただしタイムゾーンが絡む場合はtimestamptzに注意してください。
月初を取得する基本テクニック
date_truncを使う方法
日付や時刻の丸めにはdate_truncが便利です。
date_trunc('month', timestamp)はその月の先頭の時刻を返します。
例えばtodayの月初を取得する例です。
次のSQLは現在の日付の月初をtimestampとして返します。
SELECT date_trunc('month', now()) AS month_start;結果はタイムスタンプ(例: 2026-03-01 00:00:00+00)になります。
date_truncを使えば簡潔に月初を得られます。
date型で日付だけ取得する
日付だけが欲しい場合はdateにキャストします。
date_truncの結果を::dateでキャストするのが一般的です。
SELECT date_trunc('month', now())::date AS month_start_date;こうすると時刻情報が切り捨てられ、扱いやすいdate型になります。
多くの業務処理ではdate型の方が扱いやすいです。
月末を取得する代表的な方法
月初に1か月足して1日引く
最もよく使われる方法は「月初 + 1 month – 1 day」です。
これでその月の最終日を正しく求められます。
SELECT (date_trunc('month', now()) + interval '1 month' - interval '1 day')::date AS month_end;この書き方は閏年や月ごとの日数の違いも気にせず動作します。
可読性と汎用性が高いのが利点です。
make_dateとextractを使う方法
別の方法としてextractで年と月を取り出してmake_dateを使う手もあります。
年と月を直接扱うと意図が明確になります。
SELECT make_date(extract(year FROM current_date)::int,
extract(month FROM current_date)::int,
1) + interval '1 month' - interval '1 day';やや長めですが、型が明確で堅牢です。
SQLの可読性を重視する場合に向きます。
特定の条件で使う実践例
任意の日付の月初・月末
カラムのdateやtimestampを基準に月初・月末を求める場合はそのカラムをdate_truncに渡します。
次の例はordersテーブルのorder_dateを基準に月初・月末を求めるクエリです。
SELECT order_id,
order_date::date AS order_day,
date_trunc('month', order_date)::date AS month_start,
(date_trunc('month', order_date) + interval '1 month' - interval '1 day')::date AS month_end
FROM orders;
これにより各注文レコードに対応する月の開始日と終了日を出力できます。
集計や請求処理で便利です。
前月の月初・月末を取得する
前月の月初・月末を取得するにはnow()の代わりにnow() - interval '1 month'を使います。
例を示します。
SELECT date_trunc('month', now() - interval '1 month')::date AS prev_month_start,
(date_trunc('month', now() - interval '1 month') + interval '1 month' - interval '1 day')::date AS prev_month_end;会計や月次レポートの自動生成でよく使うパターンです。
シンプルでわかりやすいです。
月ごとの集計に使うテクニック
date_truncでグルーピング
月単位で集計する場合、date_truncをGROUP BYに使うと便利です。
次は売上を月ごとに集計する例です。
SELECT date_trunc('month', sold_at)::date AS month,
SUM(amount) AS total_amount
FROM sales
GROUP BY date_trunc('month', sold_at)
ORDER BY month;date_truncをSELECTとGROUP BYで同じ式にすると正しく集計されます。
表示用に::dateで整形すると見やすくなります。
月末を境にフィルタする
ある月の範囲でデータを抽出するときは月初と月末を使うのが安全です。
BETWEENで指定する例を示します。
SELECT *
FROM events
WHERE event_date BETWEEN date_trunc('month', current_date)::date
AND (date_trunc('month', current_date) + interval '1 month' - interval '1 day')::date;この方法で月の初日から末日までを漏れなく抽出できます。
境界条件のバグ防止に役立ちます。
パフォーマンスと運用上の注意点
関数を多用するとインデックスが効かない場合があります。
特にWHERE句でカラムに対して関数を適用すると注意が必要です。
可能なら月初をあらかじめ計算して保存する列を用意すると高速化できます。
あるいは関数を使った式インデックスを作成する方法もあります。
-- 式インデックスの例: sold_atの月初でインデックスを作成
CREATE INDEX idx_sales_month_start ON sales ((date_trunc('month', sold_at)));式インデックスを使えば、date_truncを使った検索でもインデックスが利用されます。
ただしインデックス作成はディスクと更新コストを伴う点に注意してください。
よくあるトラブルと対処法
時刻がずれる(タイムゾーン問題)
timestamptzを扱うとUTCとローカルの差で日付がずれることがあります。
対処としてはdateにキャストするかタイムゾーンを明示的に変換します。
SELECT date_trunc('month', timezone('Asia/Tokyo', shipped_at))::date
FROM shipments;業務ロジックに合わせてタイムゾーンを統一するのが安全です。
特に夜中の処理は注意してください。
月末を含む境界条件のミス
月末を求める計算が誤る原因は、時刻型と日付型の混同です。
必ず::dateで日付に切り替えてから比較する習慣をつけましょう。
また、BETWEENを使う場合は両端を含む挙動を理解しておくことが大切です。
時間情報があるなら半開区間を使うのも一案です。
まとめと実務への提案
ポイントはシンプルです。
date_truncで月初を求め、1か月足して1日引くことで月末が確実に得られます。
実務でのおすすめは次の通りです。
・集計用途はdate_truncで統一する。・WHEREの高速化は式インデックスや列を用いる。
この記事の例をコピペして試せば、月初・月末の処理はすぐに安定します。
必要に応じてタイムゾーンや型変換の部分だけ調整してください。
以上でPostgreSQLにおける月初・月末取得の基本と実践例の解説を終わります。
困ったときは具体的なテーブル構成や使用例を教えてください。より適切なSQLを提案します。
postgreSQLは、現場でも広く使われている信頼性の高いデータベースです。もしこれから本格的に学び、実務で通用する力をつけたい方には、RareTECHをチェックしてみてください。実案件ベースのカリキュラムで、あなたのスキルを次のステージへ引き上げてくれるはずです。
なんくる「本当にエンジニアとしてやっていけるか不安…」という方も、実践的な開発に関わることで、転職後の働き方を事前に体感できますよ。
実務で使えるDBスキルとともに、プログラミングスキルをちゃんと身につけたいなら、
RareTECHの無料カウンセリングで、学ぶ目的やゴールをプロと一緒に明確にしてみましょう。独学では得られない「実践的な成長の道筋」が見えてきます。


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










コメント