MySQL周日期查詢之精準獲取上周/本周的周一和周日全攻略
在業(yè)務(wù)開發(fā)中,“查詢上周/本周的周一、周日”是非常高頻的需求:比如統(tǒng)計上周的銷售數(shù)據(jù)、生成本周的排班表、按周匯總報表等。但很多開發(fā)者在寫這類SQL時容易踩坑:要么搞混MySQL中周的定義(周一還是周日為一周第一天),要么邊界情況處理錯誤(比如當(dāng)前是周一/周日時結(jié)果不對),導(dǎo)致查詢的數(shù)據(jù)范圍不準確。
MySQL提供了豐富的日期處理函數(shù),但不同函數(shù)對周的定義差異很大,選錯函數(shù)或邏輯會直接導(dǎo)致結(jié)果錯誤。本文將從MySQL周的定義出發(fā),全面講解如何精準獲取上周的周一、上周的周日、本周的周一、本周的周日,所有SQL均經(jīng)過多場景驗證,同時提供不同周定義下的適配方案,幫助你一次性寫對周日期查詢SQL。
一、前置知識:MySQL中周的核心定義
在開始寫SQL之前,必須先明確MySQL中兩個最常用的周相關(guān)函數(shù)的定義,這是90%的錯誤根源:
1.1 兩個核心周函數(shù)的區(qū)別
| 函數(shù) | 返回值范圍 | 對應(yīng)星期 | 核心特點 |
|---|---|---|---|
| WEEKDAY(date) | 0-6 | 0=周一, 1=周二, …, 6=周日 | 國內(nèi)常用,以周一為一周第一天 |
| DAYOFWEEK(date) | 1-7 | 1=周日, 2=周一, …, 7=周六 | 歐美常用,以周日為一周第一天 |
核心結(jié)論:本文默認采用**國內(nèi)業(yè)務(wù)最常用的“周一為一周第一天”**的定義,基于WEEKDAY()函數(shù)實現(xiàn);如果你的業(yè)務(wù)以周日為一周第一天,請看本文第四章的適配方案。
1.2 本文的時間基準
所有SQL均以CURDATE()(當(dāng)前日期)為基準,你可以將CURDATE()替換為任意日期字段(比如create_time)或具體日期(比如'2026-03-23'),靈活適配不同場景。
二、核心需求實現(xiàn):精準獲取上周/本周的周一、周日
2.1 獲取本周的周一(最基礎(chǔ)、最常用)
核心邏輯
- 用
WEEKDAY(CURDATE())獲取當(dāng)前日期是星期幾(0=周一); - 用
DATE_SUB()減去對應(yīng)的天數(shù),即可得到本周的周一:- 如果今天是周一(WEEKDAY=0):減0天,就是今天;
- 如果今天是周二(WEEKDAY=1):減1天,回到周一;
- …
- 如果今天是周日(WEEKDAY=6):減6天,回到本周一。
SQL語句
-- 獲取本周的周一(周一為一周第一天) SELECT DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) AS 本周一;
示例驗證
假設(shè)當(dāng)前日期是2026-03-25(周三):
WEEKDAY('2026-03-25')返回2(周三);DATE_SUB('2026-03-25', INTERVAL 2 DAY)返回2026-03-23(周一),結(jié)果正確。
2.2 獲取本周的周日
核心邏輯
- 先按2.1的方法獲取本周的周一;
- 本周的周一加上6天,就是本周的周日(周一+1天=周二,…,+6天=周日)。
SQL語句
-- 獲取本周的周日(周一為一周第一天) SELECT DATE_ADD(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 6 DAY) AS 本周日;
簡化寫法(更直觀)
-- 用DATE_SUB的負數(shù)等價于DATE_ADD,寫法更簡潔 SELECT DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) - 6 DAY) AS 本周日;
示例驗證
假設(shè)當(dāng)前日期是2026-03-25(周三):
- 本周一是
2026-03-23; - 加6天得到
2026-03-29(周日),結(jié)果正確。
2.3 獲取上周的周一
核心邏輯
- 先按2.1的方法獲取本周的周一;
- 本周的周一減去7天,就是上周的周一。
SQL語句
-- 獲取上周的周一(周一為一周第一天) SELECT DATE_SUB(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 7 DAY) AS 上周一;
示例驗證
假設(shè)當(dāng)前日期是2026-03-25(周三):
- 本周一是
2026-03-23; - 減7天得到
2026-03-16(上周的周一),結(jié)果正確。
2.4 獲取上周的周日(最巧妙的寫法)
核心邏輯
這里有一個非常巧妙的邏輯,不需要先算上周一再算上周日:
- 先按2.1的方法獲取本周的周一;
- 本周的周一減去1天,就是上周的周日(本周一的前一天,自然是上周的最后一天)。
SQL語句
-- 獲取上周的周日(周一為一周第一天,推薦寫法) SELECT DATE_SUB(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 1 DAY) AS 上周日;
示例驗證
假設(shè)當(dāng)前日期是2026-03-25(周三):
- 本周一是
2026-03-23; - 減1天得到
2026-03-22(上周的周日),結(jié)果正確。
邊界情況驗證
如果當(dāng)前日期是2026-03-23(周一):
- 本周一是
2026-03-23; - 減1天得到
2026-03-22(上周的周日),結(jié)果依然正確。
三、實戰(zhàn)場景:結(jié)合業(yè)務(wù)查詢周數(shù)據(jù)
掌握了基礎(chǔ)的周日期獲取后,我們結(jié)合實際業(yè)務(wù)場景,看看如何用這些SQL查詢周數(shù)據(jù)。
3.1 場景一:查詢上周的所有訂單數(shù)據(jù)
需求
查詢order_info表中,上周周一00:00:00到上周日23:59:59的所有訂單。
SQL語句
-- 定義上周的開始和結(jié)束時間 SET @last_monday = DATE_SUB(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 7 DAY); SET @last_sunday = DATE_SUB(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 1 DAY); -- 查詢上周的訂單(時間范圍:上周一00:00:00 到 上周日23:59:59) SELECT * FROM order_info WHERE create_time >= @last_monday AND create_time < DATE_ADD(@last_sunday, INTERVAL 1 DAY);
注意:用< 上周日+1天代替<= 上周日23:59:59,可以避免處理時間的時分秒,更簡潔且不會遺漏數(shù)據(jù)。
3.2 場景二:查詢本周的用戶注冊數(shù)據(jù)
需求
查詢user_info表中,本周一到今天的新增用戶數(shù)(按天分組)。
SQL語句
-- 定義本周一 SET @this_monday = DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY); -- 查詢本周一到今天的新增用戶,按天分組 SELECT DATE(create_time) AS 日期, COUNT(*) AS 新增用戶數(shù) FROM user_info WHERE create_time >= @this_monday AND create_time < DATE_ADD(CURDATE(), INTERVAL 1 DAY) GROUP BY DATE(create_time) ORDER BY 日期;
3.3 場景三:生成上周和本周的日期范圍
需求
一次性獲取上周和本周的周一、周日,生成報表的日期范圍。
SQL語句
SELECT -- 上周 DATE_SUB(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 7 DAY) AS 上周一, DATE_SUB(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 1 DAY) AS 上周日, -- 本周 DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) AS 本周一, DATE_ADD(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 6 DAY) AS 本周日;
四、適配方案:以周日為一周第一天的寫法
如果你的業(yè)務(wù)采用**歐美常用的“周日為一周第一天”**的定義(比如國際業(yè)務(wù)、外企系統(tǒng)),可以用DAYOFWEEK()函數(shù)實現(xiàn),邏輯類似,只是調(diào)整了天數(shù)計算。
4.1 核心函數(shù)說明
DAYOFWEEK(date)返回1-7,對應(yīng):
1=周日, 2=周一, …, 7=周六
4.2 完整SQL(周日為一周第一天)
SELECT -- 上周日(上周的第一天) DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE()) - 1 DAY) - INTERVAL 7 DAY AS 上周日, -- 上周六(上周的最后一天) DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE()) DAY) AS 上周六, -- 本周日(本周的第一天) DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE()) - 1 DAY) AS 本周日, -- 本周六(本周的最后一天) DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE()) - 1 DAY), INTERVAL 6 DAY) AS 本周六;
五、避坑指南:90%的人都會犯的周日期錯誤
5.1 坑一:搞混WEEKDAY和DAYOFWEEK的定義
很多人不看函數(shù)文檔,想當(dāng)然認為WEEKDAY的0是周日,或者DAYOFWEEK的1是周一,導(dǎo)致結(jié)果差了一天。
避坑方案:
- 用之前先測試一下函數(shù)返回值:
SELECT WEEKDAY(CURDATE()), DAYOFWEEK(CURDATE()); - 本文的SQL默認用
WEEKDAY(周一為第一天),如果用DAYOFWEEK請看第四章。
5.2 坑二:處理時間范圍時遺漏時分秒
查詢周數(shù)據(jù)時,用create_time <= 上周日會遺漏上周日當(dāng)天的00:00:01到23:59:59的數(shù)據(jù),因為create_time通常是DATETIME類型,包含時分秒。
避坑方案:
- 用
< 上周日+1天代替<= 上周日,自動包含上周日的所有時間; - 或者顯式拼接時分秒:
create_time <= CONCAT(@last_sunday, ' 23:59:59')。
5.3 坑三:邊界情況處理錯誤
比如當(dāng)前是周一的時候,獲取“本周的周一”應(yīng)該是今天,獲取“上周的周日”應(yīng)該是昨天;當(dāng)前是周日的時候,獲取“本周的周日”應(yīng)該是今天。
避坑方案:
- 用本文提供的SQL,已經(jīng)經(jīng)過邊界情況驗證;
- 測試時用具體的邊界日期驗證:比如
CURDATE()替換為'2026-03-23'(周一)、'2026-03-29'(周日)。
5.4 坑四:不同MySQL版本的WEEK模式差異
MySQL的WEEK()函數(shù)有多種模式,但本文用的是WEEKDAY()和DAYOFWEEK(),這兩個函數(shù)在所有MySQL版本(5.7、8.0、8.4)中的定義都是一致的,沒有版本差異,可以放心使用。
六、總結(jié):周日期查詢速查表
為了方便大家直接復(fù)制使用,我們整理了周一為一周第一天的速查表:
| 需求 | SQL語句 |
|---|---|
| 獲取本周的周一 | DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) |
| 獲取本周的周日 | DATE_ADD(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 6 DAY) |
| 獲取上周的周一 | DATE_SUB(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 7 DAY) |
| 獲取上周的周日 | DATE_SUB(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 1 DAY) |
核心結(jié)論:
- 優(yōu)先明確周的定義(周一還是周日為第一天),國內(nèi)業(yè)務(wù)默認用周一;
- 基于
WEEKDAY()函數(shù)的邏輯最直觀,且經(jīng)過多場景驗證; - 查詢時間范圍時,用
< 結(jié)束日期+1天避免遺漏時分秒; - 所有SQL都可以將
CURDATE()替換為任意日期字段,靈活適配業(yè)務(wù)。
以上就是MySQL周日期查詢之精準獲取上周/本周的周一和周日全攻略的詳細內(nèi)容,更多關(guān)于MySQL日期查詢的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
從云數(shù)據(jù)遷移服務(wù)看MySQL大表抽取模式的原理解析
這篇文章主要介紹了從云數(shù)據(jù)遷移服務(wù)看MySQL大表抽取模式的原理解析,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02
VS2019連接mysql8.0數(shù)據(jù)庫的教程圖文詳解
這篇文章主要介紹了VS2019連接mysql8.0數(shù)據(jù)庫的教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05
MySQL數(shù)據(jù)遷移相關(guān)總結(jié)
這篇文章主要介紹了MySQL數(shù)據(jù)遷移的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用MySQL數(shù)據(jù)庫,感興趣的朋友可以了解下2021-04-04

