CodeGym /課程 /SQL SELF /日期部分提取:EXTRACT() 和 AGE()

日期部分提取:EXTRACT() 和 AGE()

SQL SELF
等級 31 , 課堂 2
開放

今天我們又要來深入玩玩時間資料,學怎麼用 EXTRACT() 從裡面抓出特定部分(像是年、月或星期幾),還有怎麼用 AGE() 算年齡或兩個日期之間的時間差。

在實際專案裡,處理時間資料常常會需要把日期或時間拆開來用。舉例來說:

  • 把訂單依照年份或月份分類;
  • 算某一天註冊的用戶數量;
  • 分析兩個事件之間的時間長度。

這種需求我們就會用到 EXTRACT()AGE() 這兩個函數。

什麼是 EXTRACT()

EXTRACT() 這個函數可以讓你從日期或時間戳裡面抓出你要的部分。比如說,你可以抓出生日的年份、月份,甚至星期幾。

語法:

EXTRACT(part FROM source)
  • part:你想要抓的日期部分。可以是 YEARMONTHDAYHOURMINUTESECOND 等等。
  • 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() 這個函數是用來算兩個時間戳之間的差距。比如說,你可以用來算客戶的年齡,或是某個訂單到現在過了多久。

語法:

AGE(timestamp1, timestamp2)
  • timestamp1:比較晚的那個時間戳。
  • timestamp2:比較早的那個時間戳。
  • 如果只給一個參數,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

這裡我們算出兩個事件之間的時間間隔。這在你要計算任務開始到結束花了多久時很有用。

範例 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 型別抓月份這種不合理的部分。記得:YEARMONTHDAY 這些只能用在 DATETIMESTAMP,不能用在 TIME
  • 時間資料格式不一樣的問題。像 2023/11/15 這種寫法不是日期,記得用 ::DATETO_DATE() 轉型。
  • AGE() 跟直接減時間戳的差別。如果你要精確的間隔(幾個月、幾天、幾秒)就用 AGE(),如果只想知道天數,直接做減法就好。

現在你已經有所有必要的技能,可以在 PostgreSQL 裡面隨意抓取和分析時間資料的部分了。快去你的專案裡玩玩 EXTRACT()AGE() 吧!

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION