日期和時間不只是抽象的數字,而是資料裡超有價值的資訊關鍵!現實生活中你常常會遇到日期:像是按月份分析銷售、根據員工生日篩選,或是比較時間區間。會玩日期,查詢就能更靈活,分析也能更進階!
哪些情境下日期操作超重要:
- 分析某個月的銷售數據。
- 計算過去一年註冊的用戶數。
- 依照時間區間產生報表(像是每月收入)。
PostgreSQL 有超多日期相關的函數,這裡我們先看最實用的幾個。
日期和時間的基本函數
函數 NOW() 會回傳資料庫伺服器的現在日期和時間。你想知道此刻的精確時間就用它。舉例:你要記錄新資料建立的時間。
SELECT NOW();
範例結果:
2023-11-05 15:23:45.123456+00
使用範例: 你想插入一筆訂單,記錄現在的日期和時間:
INSERT INTO orders (order_id, order_date, total_amount)
VALUES (1, NOW(), 150.00);
註解:這裡
NOW() 會自動把現在的日期和時間加到
order_date 欄位。
INSERT 的詳細玩法我們之後會講,敬請期待 :P
函數 CURRENT_DATE
如果你只想要日期,不要時間,就用 CURRENT_DATE。它只會回傳年、月、日。
語法:
SELECT CURRENT_DATE;
範例結果:
2023-11-05
使用範例: 假設你想查詢今天的訂單:
SELECT *
FROM orders
WHERE order_date = CURRENT_DATE;
註解:這裡我們把
order_date 欄位的日期和今天的日期做比較。
來點幽默:NOW() 就像你上班的咖啡,馬上現做現喝;CURRENT_DATE 就像牆上的月曆,只給你日期,沒有多餘細節。
用 DATE_PART() 抽取日期部分
DATE_PART() 這個函數可以讓你抽出日期的某個部分,像是年、月、日、時、分。舉例:你想算某一年的訂單數,或是找出星期幾。
語法:
DATE_PART('部分', 日期)
範例:
SELECT DATE_PART('year', NOW()) AS current_year;
範例結果:
| current_year |
|---|
| 2025 |
可以抽取的日期部分:
year:年。month:月。day:日。hour:小時。minute:分鐘。second:秒。dow:星期幾(0 = 星期日)。
範例 2:抽出現在日期的月份。
SELECT DATE_PART('month', CURRENT_DATE) AS current_month;
結果:
| current_month |
|---|
| 6 |
DATE_PART() 也能用來做進階運算。舉例:
你想選出今年出生的學生:
SELECT *
FROM students
WHERE DATE_PART('year', birth_date) = DATE_PART('year', CURRENT_DATE);
範例結果:
| id | first_name | last_name | birth_date | grade |
|---|---|---|---|---|
| 1 | Otto | Art | 2025-03-12 | 9 |
| 2 | Anna | Pal | 2025-07-08 | 8 |
| 3 | Piu | Wolf | 2025-01-22 | 10 |
| 4 | Eva | Go | 2025-09-30 | 7 |
| 5 | Dan | Sok | 2025-06-14 | 9 |
實戰範例
有些範例會用到你還沒學過的語法,別擔心,很快你就能輕鬆搞定這些查詢啦!主要是想多給你看點真實案例,也順便賣個關子 :)
範例 1:計算用戶年齡
假設我們有一個 users 表,裡面有每個用戶的生日。我們想算出他們的年齡。
查詢:
SELECT user_id, first_name, last_name,
DATE_PART('year', CURRENT_DATE) - DATE_PART('year', birth_date) AS age
FROM users;
我們直接用現在的年份減掉生日的年份。這方法快,但不是最精確的年齡計算。
範例結果:
| user_id | first_name | last_name | age |
|---|---|---|---|
| 101 | Alex | Lin | 25 |
| 102 | Maria | Chi | 30 |
| 103 | Tor | Coz | 22 |
| 104 | Nat | Ive | 27 |
| 105 | Don | Sok | 35 |
範例 2:根據時間篩選
你想查詢過去一小時內的所有訂單:
SELECT *
FROM orders
WHERE order_date >= NOW() - INTERVAL '1 hour';
注意 INTERVAL(時間區間)用起來超方便!
範例 3:按月份分組
你想統計今年每個月的訂單數:
SELECT DATE_PART('month', order_date) AS order_month, COUNT(*) AS order_count
FROM orders
WHERE DATE_PART('year', order_date) = DATE_PART('year', CURRENT_DATE)
GROUP BY DATE_PART('month', order_date)
ORDER BY order_month;
這裡是用月份分組,然後按月份排序。
範例結果:
| order_month | order_count |
|---|---|
| 1 | 120 |
| 2 | 95 |
| 3 | 134 |
| 4 | 110 |
| 5 | 42 |
範例 4:抽出星期幾
你想知道哪一天訂單最多:
SELECT DATE_PART('dow', order_date) AS day_of_week, COUNT(*) AS order_count
FROM orders
GROUP BY DATE_PART('dow', order_date)
ORDER BY order_count DESC;
DATE_PART('dow') 會回傳每筆訂單的星期幾(0 是星期日,1 是星期一,以此類推)。DOW 就是 DayOfWeek 的縮寫。
範例結果:
| day_of_week | order_count |
|---|---|
| 5 | 210 |
| 4 | 190 |
| 3 | 175 |
| 2 | 160 |
| 1 | 140 |
| 6 | 120 |
| 0 | 95 |
注意常見錯誤
處理日期常常讓人頭痛,因為很容易出錯。這裡列幾個你可能會遇到的常見問題:
時間和日期格式: 用 NOW() 或其他會回傳日期時間的函數時,一定要注意格式。像是你拿 order_date 跟 CURRENT_DATE 比較時,要確定時間部分有被忽略或明確指定。
日期是字串格式: 很多資料庫會把日期存成字串(像是 text)。如果你直接用日期函數(像 DATE_PART()),就會出錯。記得資料型態要是 DATE 或 TIMESTAMP。
時區不同: 如果你的伺服器和資料來源在不同時區,可能會搞混。建議用 TIMESTAMPTZ 處理時區。
GO TO FULL VERSION