資料庫開發中,依日期區間篩選資料是極高頻需求。本文整理 MySQL 日期查詢的標準寫法、進階技巧與效能陷阱,助您撰寫既正確又高效的 SQL。
查詢 cangku 表中 shijian 欄位落於 2011-01-13 至 2011-01-20 之間的記錄:
SELECT * FROM `cangku`
WHERE `shijian` >= '2011-01-13' AND `shijian` <= '2011-01-20';
推薦改用 BETWEEN: 可讀性更佳,且包含邊界值。
SELECT * FROM `cangku`
WHERE `shijian` BETWEEN '2011-01-13' AND '2011-01-20';
SELECT * FROM `tables`
WHERE MONTH(`Date`) = MONTH(NOW())
AND YEAR(`Date`) = YEAR(NOW());
效能警示: 對欄位使用函數(MONTH()、YEAR())會導致索引失效(全表掃描)。大量資料時請改用區間查詢:
SELECT * FROM `tables`
WHERE `Date` >= DATE_FORMAT(NOW(), '%Y-%m-01')
AND `Date` < DATE_ADD(DATE_FORMAT(NOW(), '%Y-%m-01'), INTERVAL 1 MONTH);
SELECT * FROM `orders`
WHERE `created_at` >= DATE_SUB(NOW(), INTERVAL 30 DAY);
| 型別 | 儲存範圍 | 時區處理 | 適用場景 |
|---|---|---|---|
| DATETIME | 1000-01-01 ~ 9999-12-31 | 不轉換,原樣儲存 | 固定時區應用、歷史資料 |
| TIMESTAMP | 1970-01-01 ~ 2038-01-19 | 寫入轉 UTC,讀出轉回 session 時區 | 跨時區應用、自動記錄建立/更新時間 |
| DATE | 1000-01-01 ~ 9999-12-31 | 無時區概念 | 僅需日期(生日、截止日) |
WHERE DATE(created_at) = '2023-01-01' ❌ → WHERE created_at >= '2023-01-01' AND created_at < '2023-01-02' ✅INDEX idx_user_date (user_id, created_at) 可同時支援「某用戶某期間」查詢。RANGE COLUMNS(created_at) 分區,實現分區裁剪。| 需求 | SQL 片段 |
|---|---|
| 今日資料 | WHERE `dt` >= CURDATE() |
| 本週資料(週一起) | WHERE `dt` >= DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) |
| 本季資料 | WHERE QUARTER(`dt`) = QUARTER(NOW()) AND YEAR(`dt`) = YEAR(NOW()) |
| 跨年週期(如 12/25 ~ 01/05) | WHERE (`dt` >= '2023-12-25' AND `dt` < '2024-01-06') |
掌握日期查詢的核心在於:「用區間替代函數、善用索引、注意時區」。將這些原則內化為編碼習慣,查詢效能與正確性將雙雙提升。