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

MySQL 相對時間查詢大全:今日、昨日、近 7/30 天、本月、上月 SQL 範本

     編輯:MySQL 綜合教學

報表、儀表板、定時任務頻繁需要「相對時間」篩選。本文提供針對 DATETIME/TIMESTAMP/INT Unix時間戳 三種欄位類型的標準 SQL 範本,並解析核心函數 TO_DAYS、DATE_SUB、DATE_FORMAT、PERIOD_DIFF 差異與陷阱。

欄位類型別範本

1. DATETIME / TIMESTAMP 欄位(推薦)

-- 今日
WHERE DATE(add_time) = CURDATE()
-- 或
WHERE add_time >= CURDATE() AND add_time < CURDATE() + INTERVAL 1 DAY

-- 昨日
WHERE DATE(add_time) = CURDATE() - INTERVAL 1 DAY

-- 近 7 天(含今日)
WHERE add_time >= DATE_SUB(CURDATE(), INTERVAL 6 DAY)

-- 近 30 天
WHERE add_time >= DATE_SUB(CURDATE(), INTERVAL 29 DAY)

-- 本月
WHERE DATE_FORMAT(add_time, '%Y%m') = DATE_FORMAT(CURDATE(), '%Y%m')

-- 上月
WHERE PERIOD_DIFF(DATE_FORMAT(CURDATE(), '%Y%m'), DATE_FORMAT(add_time, '%Y%m')) = 1

2. INT Unix 時間戳欄位

-- 今日
WHERE DATE_FORMAT(FROM_UNIXTIME(add_time), '%Y-%m-%d') = DATE_FORMAT(NOW(), '%Y-%m-%d')

-- 近 7 天
WHERE FROM_UNIXTIME(add_time) >= DATE_SUB(NOW(), INTERVAL 7 DAY)

核心函數解析

函數作用陷阱
TO_DAYS(date)日期轉天數(從 year 0)1582 年前不可靠;僅精確到天
DATE_SUB(date, INTERVAL n UNIT)日期減法單位支援 DAY/MONTH/YEAR/HOUR/MINUTE/SECOND
DATE_FORMAT(date, fmt)日期格式化%Y%m 適合月份比較;%Y-%m-%d 適合天比較
PERIOD_DIFF(p1, p2)月份差(YYYYMM 格式)僅支援 YYYYMM,不支援 YYYY-MM
STR_TO_DATE(str, fmt)字串轉日期格式必須嚴格匹配,否則返回 NULL

效能最佳實踐:避免在欄位上用函數

錯誤:WHERE DATE(add_time) = CURDATE() → 全表掃描,無法用索引。
正確:WHERE add_time >= '2023-10-01 00:00:00' AND add_time < '2023-10-02 00:00:00' → 可用 add_time 索引範圍掃描。

應用層組裝範例

function getDateRangeSql($field, $range) {
    $now = new DateTime();
    switch ($range) {
        case 'today':
            $start = (clone $now)->setTime(0,0,0);
            $end = (clone $now)->setTime(23,59,59);
            break;
        case 'yesterday':
            $start = (clone $now)->modify('-1 day')->setTime(0,0,0);
            $end = (clone $start)->setTime(23,59,59);
            break;
        case '7days':
            $start = (clone $now)->modify('-6 days')->setTime(0,0,0);
            $end = (clone $now)->setTime(23,59,59);
            break;
        case '30days':
            $start = (clone $now)->modify('-29 days')->setTime(0,0,0);
            $end = (clone $now)->setTime(23,59,59);
            break;
        case 'this_month':
            $start = (clone $now)->modify('first day of this month')->setTime(0,0,0);
            $end = (clone $now)->modify('last day of this month')->setTime(23,59,59);
            break;
        case 'last_month':
            $start = (clone $now)->modify('first day of last month')->setTime(0,0,0);
            $end = (clone $now)->modify('last day of last month')->setTime(23,59,59);
            break;
    }
    return "`$field` >= '{$start->format('Y-m-d H:i:s')}' AND `$field` <= '{$end->format('Y-m-d H:i:s')}'";
}

避坑清單

  • BETWEEN 含邊界,DATETIME 精度到秒,易漏掉 23:59:59.xxx → 改用 >= start AND < end+1day。
  • CURDATE() 返回日期,NOW() 返回日期時間,**別混用**導致隱式轉換。
  • 跨時區業務:統一儲存 UTC,查詢時在應用層換算時區再組裝範圍。
  • 分區表:WHERE 條件必須包含分區鍵,否則全分區掃描。

相對時間查詢看似簡單,**欄位類型、索引利用、時區、邊界** 四個坑踩一個就慢或錯。將上述範本封裝為工具函數/ORM Scope,業務代碼直接呼叫,才能保證一致性與效能。

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