今日はまた時間データの操作を深掘りして、EXTRACT() 関数で年・月・曜日みたいな特定の部分を取り出す方法と、AGE() 関数で年齢や日付間の間隔を計算する方法を勉強しよう!
実際のプロジェクトで時間データを扱うとき、日付や時刻の特定の部分を抜き出したいことがよくあるんだ。例えば:
- 注文を年や月ごとに分ける;
- 特定の曜日に登録したユーザー数を数える;
- 2つのイベントの間の時間の長さを分析する。
こういうタスクには EXTRACT() と AGE() を使うよ。
EXTRACT() って何?
EXTRACT() 関数は日付やタイムスタンプから特定の部分を取り出せるんだ。例えば誕生日から年だけ抜き出したり、月番号を調べたり、曜日を取り出したりできるよ。
構文:
EXTRACT(part FROM source)
part: 取り出したい日付の部分。YEAR、MONTH、DAY、HOUR、MINUTE、SECONDなどが使える。source: 情報を取り出す時間型データ。カラム、定数、関数の結果などが指定できる。
例1: 年・月・日を取り出す
SELECT
EXTRACT(YEAR FROM '2024-11-15'::DATE) AS year_part,
EXTRACT(MONTH FROM '2024-11-15'::DATE) AS month_part,
EXTRACT(DAY FROM '2024-11-15'::DATE) AS day_part;
結果:
| year_part | month_part | day_part |
|---|---|---|
| 2024 | 11 | 15 |
ここでは 2024-11-15 という日付から年・月・日を取り出してるよ。こういうやり方は、日付の特定の部分でデータをグループ化したいときに便利!
例2: 曜日と時刻から時間を取り出す
SELECT
EXTRACT(DOW FROM '2024-11-15'::DATE) AS day_of_week,
EXTRACT(HOUR FROM '15:30:00'::TIME) AS hour_part;
結果:
| day_of_week | hour_part |
|---|---|
| 3 | 15 |
DOW(Day of Week) は曜日番号を返すよ:日曜日は0、月曜日は1、みたいな感じ。HOURは時刻から時間部分を取り出す。
例3: カラムに使う場合
もし日付が入ったテーブルがあれば、分析のために日付の一部を取り出せるよ。例えば orders というテーブルがあるとする:
| order_id | order_date |
|---|---|
| 1 | 2023-05-12 14:20 |
| 2 | 2023-06-18 10:45 |
| 3 | 2023-07-22 21:15 |
SELECT
order_id,
EXTRACT(MONTH FROM order_date) AS month,
EXTRACT(DAY FROM order_date) AS day
FROM orders;
結果:
| order_id | month | day |
|---|---|---|
| 1 | 5 | 12 |
| 2 | 6 | 18 |
| 3 | 7 | 22 |
AGE() って何?
AGE() 関数は2つのタイムスタンプの差を計算するために使うよ。例えば、顧客の誕生日から年齢を計算したり、注文からどれくらい時間が経ったかを調べたりできる。
構文:
AGE(timestamp1, timestamp2)
timestamp1: より新しいタイムスタンプ。timestamp2: より古いタイムスタンプ。- パラメータを1つだけ指定した場合、PostgreSQL は自動的に現在の日付 (
NOW()) と比較してくれる。
例1: 年齢の計算
SELECT AGE('2025-11-15'::DATE, '1990-05-12'::DATE) AS age;
結果:
| age |
|---|
| 35 years 6 mons |
この例は、1990年5月12日生まれの人が2025年11月15日時点で何歳かを示してるよ。
例2: イベント間の時間間隔
SELECT AGE('2023-06-01 15:00'::TIMESTAMP, '2023-05-20 10:30'::TIMESTAMP) AS duration;
結果:
| duration |
|---|
| 11 days 4:30:00 |
ここでは2つのイベントの間隔を計算してる。タスクの開始と終了の間にどれくらい時間がかかったか知りたいときに便利!
例3: 顧客の年齢
例えば customers というテーブルがあるとする:
| customer_id | birth_date |
|---|---|
| 1 | 1992-03-10 |
| 2 | 1985-07-07 |
顧客の年齢を計算してみよう:
SELECT
customer_id,
AGE(NOW(), birth_date) AS age
FROM customers;
2025年6月13日時点の結果:
| customer_id | age |
|---|---|
| 1 | 33 years 3 mons |
| 2 | 39 years 11 mons |
もちろん、みんなの NOW() の値や結果は自分の環境によって変わるよ。
EXTRACT() と AGE() の実践例
じゃあ、実際のシナリオでこれらの関数を組み合わせてみよう。
例1: 月ごとのデータ集計
注文日付きのテーブルがあるとする。月ごとの注文数を数えたいときは、こんなクエリを使う:
SELECT
EXTRACT(MONTH FROM order_date) AS order_month,
COUNT(*) AS total_orders
FROM orders
GROUP BY order_month
ORDER BY order_month;
例2: 有効期限までの日数
subscriptions というテーブルがあるとする:
| subscription_id | expiry_date |
|---|---|
| 1 | 2023-12-31 |
| 2 | 2024-05-15 |
サブスクリプションの有効期限まであと何日か知りたい場合:
SELECT
subscription_id,
AGE(expiry_date, NOW()) AS time_remaining
FROM subscriptions;
結果:
| subscription_id | time_remaining |
|---|---|
| 1 | 1 mons 15 days |
| 2 | 6 mons |
よくあるミスとその回避法
EXTRACT() や AGE() を使うとき、初心者がつまずきやすいポイントがいくつかあるよ:
TIME型から月を取り出そうとするなど、許可されてない部分を抜き出そうとする。覚えておこう:YEAR、MONTH、DAYはDATEやTIMESTAMPで使えるけど、TIMEではダメ。- 時間データのフォーマット違いによるトラブル。例えば
2023/11/15みたいな文字列は日付として認識されない。::DATEやTO_DATE()で型変換しよう。 AGE()とタイムスタンプの引き算の違い。月・日・秒単位の正確な間隔が欲しいならAGE()を使おう。単純に日数だけ欲しいなら普通の計算でもOK。
これで PostgreSQL で時間データの一部を取り出したり分析したりするスキルはバッチリ!自分のプロジェクトで EXTRACT() や AGE() をいろいろ試してみてね!
GO TO FULL VERSION