YEARWEEK函数返回值与预期不符是因为默认mode=0以周日为周起点,而业务多按周一计算;应统一使用mode=3(周一为起点且第一周含1月4日)确保跨年周归属一致,并用范围查询替代函数过滤以走索引。

YEARWEEK函数返回值为什么和预期对不上?
因为 YEARWEEK() 默认用周日作为一周起点(mode=0),而多数业务场景按周一算本周。比如2024-06-02是周日,YEARWEEK('2024-06-02') 返回 202422,但你可能希望它属于第23周(从6月3日周一算起)。
解决办法是显式指定 mode 参数:
-
mode = 1:周一为每周第一天,且第一周必须包含4个及以上周一(ISO标准) -
mode = 3:周一为每周第一天,且第一周是包含1月4日的那一周(更常用) -
mode = 5:周日为每周第一天,但第一周需含4个及以上周日(不推荐)
日常查“本周一到周日”数据,优先用 mode = 3。
如何用YEARWEEK筛选“本周”的完整记录?
不能直接写 WHERE YEARWEEK(create_time) = YEARWEEK(NOW())——这会忽略 mode 一致性,且无法走索引。正确做法是先算出本周的起止时间,再做范围查询。
例如 MySQL 中查「本周一 00:00:00 到本周日 23:59:59」的数据:
SELECT * FROM orders WHERE create_time >= DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) AND create_time < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 7 DAY);
说明:
-
WEEKDAY(CURDATE())返回当前日期是本周第几天(周一=0,周日=6) -
DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY)得到本周一 - 右边界用
<而非<=,避免跨天误差
YEARWEEK在WHERE子句中能走索引吗?
基本不能。只要对字段用了函数,如 YEARWEEK(create_time),MySQL 就无法使用 create_time 上的普通 B+Tree 索引(除非是函数索引,MySQL 8.0.13+ 支持)。
如果你的表很大,又频繁查本周数据,建议:
- 给
create_time建普通索引(覆盖范围查询场景) - 避免写
WHERE YEARWEEK(create_time) = ...这类表达式 - 若必须用函数过滤,且 MySQL ≥ 8.0.13,可建函数索引:
CREATE INDEX idx_week ON orders ( (YEARWEEK(create_time, 3)) );
但函数索引只加速该特定函数+mode组合,灵活性差,不如范围查询通用。
跨年时YEARWEEK返回202453还是202501?
取决于 mode 和日期。例如 2024-12-30 是周一,按 ISO 标准(mode=1),它属于 2025 年第 1 周,YEARWEEK('2024-12-30', 1) 返回 202501;但按 mode=3,它仍属 2024 年第 53 周。
所以跨年周的归属不是固定规则,而是由 mode 定义的“第一周”逻辑决定。线上统计报表如果按自然周(周一至周日)聚合,务必统一用 mode = 3,否则 12 月底的数据可能被分到下一年的“本周”。
真正容易被忽略的,是业务定义的“本周”和数据库函数默认行为之间的隐式偏差——不显式写 mode,等于把逻辑交给 MySQL 的默认值,而这个默认值很可能和你的日报、BI 看板不一致。

















