核心函數分類速查
| 類別 | 函數 | 返回值 | 範例結果 |
| 日期提取 | YEAR(date) | 年份 | 2024 |
MONTH(date) | 月份 1-12 | 1 |
DAY(date) / DAYOFMONTH() | 日 1-31 | 15 |
HOUR(time) | 時 0-23 | 14 |
MINUTE(time) | 分 0-59 | 30 |
SECOND(time) | 秒 0-59 | 59 |
DAYOFWEEK(date) | 星期 1(日)-7(六) | 2 (週一) |
WEEKDAY(date) | 星期 0(一)-6(日) | 0 (週一) |
| 格式化/名稱 | DAYNAME(date) | 星期英文名 | Monday |
MONTHNAME(date) | 月份英文名 | January |
DATE_FORMAT(date, fmt) | 自定義格式 | 2024-01-15 |
TIME_FORMAT(time, fmt) | 時間自定義格式 | 14:30:59 |
QUARTER(date) | 季度 1-4 | 1 |
WEEK(date, mode) | 第幾週 (mode 控制起始日/範圍) | 3 |
| 週/年組合 | YEARWEEK(date, mode) | 年週組合 | 202403 |
DAYOFYEAR(date) | 一年中的第幾天 1-366 | 15 |
PERIOD_ADD(P, N) | 年月 + N 月 (YYMM/YYYYMM) | 202402 |
PERIOD_DIFF(P1, P2) | 兩期間月數差 | 11 |
日期間隔運算(核心)
DATE_ADD(date, INTERVAL expr unit)
DATE_SUB(date, INTERVAL expr unit)
-- 同義詞:ADDDATE(), SUBDATE()
-- 常用單位:MICROSECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR
-- 組合單位:SECOND_MICROSECOND, MINUTE_MICROSECOND, MINUTE_SECOND, HOUR_MICROSECOND,
-- HOUR_SECOND, HOUR_MINUTE, DAY_MICROSECOND, DAY_SECOND, DAY_MINUTE, DAY_HOUR,
-- YEAR_MONTH
實戰範例
1. 最近 30 天記錄
SELECT * FROM orders
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY);
2. 本月第一天/最後一天
-- 本月第一天 00:00:00
SELECT DATE_FORMAT(NOW(), '%Y-%m-01 00:00:00');
-- 或
SELECT DATE_SUB(NOW(), INTERVAL DAY(NOW())-1 DAY);
-- 本月最後一天 23:59:59
SELECT LAST_DAY(NOW()) + INTERVAL 1 DAY - INTERVAL 1 SECOND;
3. 年齡計算
SELECT TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) AS age FROM users;
4. 工作日判斷
SELECT CASE WHEN WEEKDAY(created_at) < 5 THEN '工作日' ELSE '週末' END AS day_type
FROM orders;
5. 相對時間格式化(如「3 分鐘前」)
SELECT CONCAT(
CASE
WHEN TIMESTAMPDIFF(SECOND, created_at, NOW()) < 60 THEN '剛剛'
WHEN TIMESTAMPDIFF(MINUTE, created_at, NOW()) < 60 THEN CONCAT(TIMESTAMPDIFF(MINUTE, created_at, NOW()), ' 分鐘前')
WHEN TIMESTAMPDIFF(HOUR, created_at, NOW()) < 24 THEN CONCAT(TIMESTAMPDIFF(HOUR, created_at, NOW()), ' 小時前')
WHEN TIMESTAMPDIFF(DAY, created_at, NOW()) < 30 THEN CONCAT(TIMESTAMPDIFF(DAY, created_at, NOW()), ' 天前')
ELSE DATE_FORMAT(created_at, '%Y-%m-%d')
END
) AS relative_time FROM posts;
常見陷阱避坑
NOW() vs SYSDATE():NOW() 在語句開始時固定,SYSDATE() 實時獲取,複制/備份行為不同
DATE_ADD(col, INTERVAL 1 MONTH) 月末邊界:1 月 31 日 + 1 月 = 2 月 28/29 日(非 3 月 2/3 日)
- 時區一致性:資料庫、應用、JVM/容器時區統一為 UTC,顯示層轉換用戶時區
- 索引失效:
WHERE DATE(created_at) = '2024-01-15' 導致索引失效,改用範圍查詢 created_at >= '2024-01-15' AND created_at < '2024-01-16'
延伸閱讀
- 常用 MySQL 命令列工具介紹
- MySQL 無重複查詢的實現
- 五種常用的 MySQL 命令列