在 MySQL 開發中,經常需要根據當前日期動態計算「本季度第一天」、「本月第一天」或「本周第一天」。本文整理了多種實用寫法,從基礎函數到進階優化,幫助你靈活應對各類時間範圍查詢需求。
MySQL 提供多個同義函數獲取當前日期:
CURDATE()CURRENT_DATE() / CURRENT_DATENOW()(包含時間部分)建議統一使用 CURDATE() 以提高可讀性。
SELECT DATE(
CONCAT(YEAR(CURDATE()), '-', ELT(QUARTER(CURDATE()), 1, 4, 7, 10), '-01')
) AS quarter_start;
原理:QUARTER() 返回 1-4,ELT() 按索引返回對應月份(1,4,7,10),再拼接年份與「-01」。
SELECT DATE(
CONCAT(YEAR(CURDATE()), '-',
IF(QUARTER(CURDATE())=1, 1,
IF(QUARTER(CURDATE())=2, 4,
IF(QUARTER(CURDATE())=3, 7, 10))), '-01')
) AS quarter_start;
SELECT DATE(CONCAT(YEAR(CURDATE()), '-', MONTH(CURDATE()), '-01')) AS month_start;
或更簡潔:
SELECT DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE())-1 DAY) AS month_start;
SELECT DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) AS week_start;
WEEKDAY() 返回 0(周一) 到 6(周日),直接減去即可得到本周一日期。
SELECT * FROM `p8_memberdata`
WHERE regdate BETWEEN UNIX_TIMESTAMP(CURDATE()) AND UNIX_TIMESTAMP(CURDATE()) + 86399;
SELECT * FROM `p8_memberdata`
WHERE DATE(regdate) = CURDATE()
ORDER BY uid DESC;
| 需求 | 推薦寫法 | 特點 |
|---|---|---|
| 季度首日 | ELT(QUARTER(...)) | 簡潔、無嵌套、效能佳 |
| 月份首日 | DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE())-1 DAY) | 無需拼接字符串 |
| 周首日 | DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) | 標準周一定義 |
掌握這些模式,即可輕鬆構建各類時間維度的報表與統計查詢。