首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 相對時間範圍查詢速查表:今日、昨日、近 7/30 天、本月、上月、本季、上季、本年、上年

     編輯:MySQL 綜合教學

MySQL 相對時間範圍查詢速查表:今日、昨日、近 7/30 天、本月、上月、本季、上季、本年、上年

業務常需「最近 N 天」、「本月迄今」、「上季度」等相對時間統計。本文彙整最常用、索引友好的 SQL 寫法,避免 DATE_SUB(NOW()) 導致索引失效,並說明 DATE()、TO_DAYS()、DATE_FORMAT()、YEARWEEK()、QUARTER() 等函數適用場景。

一、核心原則:避免在欄位上做函數運算

-- ❌ 反例:created_at 上用函數,索引失效
WHERE DATE(created_at) = CURDATE()
WHERE DATE_SUB(NOW(), INTERVAL 7 DAY) <= DATE(created_at)

-- ✅ 正例:將計算移到常數側,欄位保持原樣,可走範圍索引
WHERE created_at >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
  AND created_at < CURDATE() + INTERVAL 1 DAY

二、常用相對時間範圍 SQL 模板

需求索引友好寫法(假設欄位 created_at 為 DATETIME/TIMESTAMP)
今日WHERE created_at >= CURDATE() AND created_at < CURDATE() + INTERVAL 1 DAY
昨日WHERE created_at >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) AND created_at < CURDATE()
近 7 天(含今日)WHERE created_at >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND created_at < CURDATE() + INTERVAL 1 DAY
近 30 天WHERE created_at >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND created_at < CURDATE() + INTERVAL 1 DAY
本月WHERE created_at >= DATE_FORMAT(CURDATE(), '%Y-%m-01') AND created_at < DATE_FORMAT(CURDATE(), '%Y-%m-01') + INTERVAL 1 MONTH
上月WHERE created_at >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01') AND created_at < DATE_FORMAT(CURDATE(), '%Y-%m-01')
本季度WHERE QUARTER(created_at) = QUARTER(NOW()) AND YEAR(created_at) = YEAR(NOW())
(或用日期範圍:created_at >= MAKEDATE(YEAR(NOW()),1) + INTERVAL QUARTER(NOW())-1 QUARTER ...)
上季度WHERE QUARTER(created_at) = QUARTER(DATE_SUB(NOW(), INTERVAL 1 QUARTER)) AND YEAR(created_at) = YEAR(DATE_SUB(NOW(), INTERVAL 1 QUARTER))
本年WHERE created_at >= MAKEDATE(YEAR(NOW()),1) AND created_at < MAKEDATE(YEAR(NOW()),1) + INTERVAL 1 YEAR
上年WHERE created_at >= MAKEDATE(YEAR(NOW())-1,1) AND created_at < MAKEDATE(YEAR(NOW()),1)
本周(週一為首日)WHERE YEARWEEK(created_at, 1) = YEARWEEK(NOW(), 1)
上周WHERE YEARWEEK(created_at, 1) = YEARWEEK(DATE_SUB(NOW(), INTERVAL 1 WEEK), 1)
最近 6 個月WHERE created_at BETWEEN DATE_SUB(NOW(), INTERVAL 6 MONTH) AND NOW()

三、函數選擇指南

  • CURDATE() / CURRENT_DATE:僅日期部分,無時間,適合「日」邊界計算。
  • NOW() / CURRENT_TIMESTAMP:含時間,適合「精確到秒」邊界。
  • DATE_SUB(date, INTERVAL n UNIT):日期減法,支援 DAY/WEEK/MONTH/QUARTER/YEAR。
  • DATE_FORMAT(date, '%Y-%m'):字串比較,會導致索引失效,僅用於小表或無索引欄位。
  • TO_DAYS(date):轉整數天數,WHERE TO_DAYS(NOW()) - TO_DAYS(created_at) <= 1 可用於「昨日」,但欄位側有函數,不如範圍查詢好。
  • YEARWEEK(date, mode):mode=1 週一為首日、mode=0 週日為首日,需與業務定義一致。
  • QUARTER(date):返回 1~4,配合 YEAR() 判斷季度。

四、分區表/大表優化提示

  • 按 RANGE COLUMNS(created_at) 分區,配合分區裁剪自動過濾無關分區。
  • 歷史歸檔表改用壓縮引擎(TokuDB、RocksDB、MyRocks)或導出至 ClickHouse/Apache Doris 做 OLAP。

收藏建議:將上表存為代碼片,需要時複製微調欄位名即可。核心口訣:「常數側算好邊界,欄位側裸奔跑索引」。

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