首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 日期範圍查詢高效寫法:當天、本週、本月、最近 N 天

     編輯:MySQL 資料庫相關知識

業務中頻繁需要按時間維度篩選數據,正確使用日期函數與索引友好寫法,能避免全表掃描,大幅提升查詢性能。本文總結常用時間範圍查詢模式。

核心原則:避免在列上使用函數

❌ 反模式(導致索引失效):

WHERE DATE(create_time) = CURDATE()
WHERE YEAR(create_time) = 2024 AND MONTH(create_time) = 1
WHERE TO_DAYS(create_time) = TO_DAYS(NOW())

✅ 推薦模式(利用索引範圍掃描):

WHERE create_time >= '2024-01-15 00:00:00' 
  AND create_time < '2024-01-16 00:00:00'

常用時間範圍構造函數

需求索引友好寫法說明
今天create_time >= CURDATE() AND create_time < CURDATE() + INTERVAL 1 DAYCURDATE() 返回 'YYYY-MM-DD'
昨天create_time >= CURDATE() - INTERVAL 1 DAY AND create_time < CURDATE()
本週(週一開始)create_time >= DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) AND create_time < DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) + INTERVAL 7 DAYWEEKDAY() 週一=0
上週create_time >= DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE())+7 DAY) AND create_time < DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY)
本月create_time >= DATE_FORMAT(CURDATE(), '%Y-%m-01') AND create_time < DATE_FORMAT(CURDATE(), '%Y-%m-01') + INTERVAL 1 MONTH首日 00:00:00
上月create_time >= DATE_FORMAT(CURDATE() - INTERVAL 1 MONTH, '%Y-%m-01') AND create_time < DATE_FORMAT(CURDATE(), '%Y-%m-01')
最近 N 天create_time >= DATE_SUB(CURDATE(), INTERVAL N DAY)包含今天
最近 N 秒/分鐘/小時create_time >= DATE_SUB(NOW(), INTERVAL N SECOND/MINUTE/HOUR)精確到秒級

應用層構造邊界值(最佳性能)

在應用代碼中計算好起止時間,直接傳參:

-- PHP 示例
$start = date('Y-m-d 00:00:00');
$end = date('Y-m-d 23:59:59');
$sql = "SELECT * FROM orders WHERE create_time BETWEEN '$start' AND '$end'";

優勢:

  • SQL 固定,利用 Query Cache / Prepared Statement
  • 避免函數計算開銷
  • 跨時區業務可在應用層統一處理

特殊場景處理

Unix 時間戳存儲(INT 類型)

-- 今天
WHERE create_time >= UNIX_TIMESTAMP(CURDATE()) 
  AND create_time < UNIX_TIMESTAMP(CURDATE() + INTERVAL 1 DAY)

-- 最近 30 秒
WHERE UNIX_TIMESTAMP(NOW()) - create_time <= 30

分區表按時間裁剪

-- 按月分區表,優化器自動分區裁剪
WHERE create_time >= '2024-01-01' AND create_time < '2024-02-01'

性能對比驗證

-- 測試表:1000 萬行,create_time 有索引
EXPLAIN SELECT * FROM logs WHERE DATE(create_time) = CURDATE();  -- type=ALL 全表掃描
EXPLAIN SELECT * FROM logs WHERE create_time >= CURDATE() AND create_time < CURDATE()+INTERVAL 1 DAY;  -- type=range 索引範圍掃描

總結

  1. 永遠使用 列 >= 起始值 AND 列 < 結束值 區間形式
  2. 應用層預計算邊界值,SQL 保持靜態
  3. 確保查詢列上有索引(單列或聯合索引最左列)
  4. 定期 ANALYZE TABLE 更新統計信息

正確的時間範圍查詢寫法,是發揮索引效能的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved