导读:本期聚焦于小伙伴创作的《如何在MySQL中获取本周一的具体日期?利用STR_TO_DATE与DATE_FORMAT组合》,敬请观看详情。算报表时经常卡在周维度统计的起始日上,如果直接拿当前日期去减天数,遇到跨年或不同区域周定义就会出错。MySQL里用DATE_FORMAT先把日期转成年份加周数,再用STR_TO_DATE还原成具体日期,能稳定得到本周一。该方法不依赖外部程序,纯SQL完成,适配周一开始的本地化习惯。下面拆解函数行为并给出可复用语句,同时对比WEEKDAY写法的边界差异,帮你避开时区与周规则导致的偏移问题。

在MySQL中做按周汇总时,经常需要把数据归到本周的周一开始计算。单纯用日期加减在跨年或跨月时容易算错,而组合使用STR_TO_DATE与DATE_FORMAT可以稳定拿到本周一,且逻辑清晰、可移植性好。

如何在MySQL中获取本周一的具体日期?利用STR_TO_DATE与DATE_FORMAT组合

一、为什么需要STR_TO_DATE与DATE_FORMAT组合

MySQL提供了很多日期函数,但并没有一个直接叫get_monday的函数。很多人会用DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY)来取周一,这确实在大多数情况可行。不过当业务要求按自然周(周一开始)且要和年份、周数强绑定时,用DATE_FORMAT把日期格式化为“年-周”再让STR_TO_DATE解析回来,会更加直观,也更容易和ISO周标准对齐。

STR_TO_DATE的作用是把字符串按照指定格式转成日期,DATE_FORMAT则是把日期格式化为字符串。两者一正一反,配合%X(年份)、%V(周数)等格式符,就可以构造出“某年某周的第一天”这样的语义,再交给STR_TO_DATE变成真正的DATE类型。这种方式在写报表SQL或存储过程时,可读性比一堆INTERVAL嵌套更好。

二、核心函数用法说明

DATE_FORMAT的常用格式符中,%X表示ISO年份,%V表示ISO周数(01到53,周一为一周开始)。例如2024年1月1日是周一,它属于2024年的第01周。我们可以用下面语句观察:

SELECT DATE_FORMAT('2024-01-01', '%X-%V') AS iso_week;
-- 结果:2024-01

STR_TO_DATE则接收字符串和格式,返回日期。需要注意的是,如果只给“年-周”还无法直接变成周一,因为STR_TO_DATE需要更完整的日期成分。通常我们拼接一个“周一”的占位,比如把格式写成'%X-%V-1',其中1表示周一,再配合格式符%w(周几,0=周日,1=周一)来解析。

一个更稳妥的写法是借用CONCAT把年、周和“周一”拼成字符串,然后让STR_TO_DATE按'%X-%V-%w'解析。这样MySQL会自动将该周数下的周一映射为具体日期,避免手动计算偏移。

三、获取本周一的完整SQL示例

下面给出一段可直接运行的SQL,用于获取本周一的具体日期:

SELECT
  STR_TO_DATE(
    CONCAT(DATE_FORMAT(CURDATE(), '%X-%V'), '-1'),
    '%X-%V-%w'
  ) AS this_monday;

这段代码中,DATE_FORMAT(CURDATE(), '%X-%V')先得到当前日期所在的ISO年和周,例如'2024-03';CONCAT加上'-1'变成'2024-03-1';STR_TO_DATE按'%X-%V-%w'解析,%w遇到1就取该周周一,于是返回2024年对应周的周一日期。

如果你希望周定义以周日为一周开始,可以把%V换成%U,并把后面的周几占位改成0(%U是周日开始计周的周数)。但要注意,业务上国内报表普遍以周一为起点,所以用%X和%V更合适。

四、与WEEKDAY写法的对比

另一种常见写法是:

SELECT DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) AS monday_by_weekday;

WEEKDAY函数返回0代表周一,6代表周日,所以用当前日期减去这个天数就能回到周一。它在绝大多数自然周场景下正确,而且不需要字符串转换,性能略好。但当数据和跨年周数强相关、或者要和ISO周字段(如按周分表名)保持一致时,STR_TO_DATE组合法在语义上更不容易出错。

从执行计划看,两种都是对常量或索引列做简单计算,开销极小。实际选型建议:若只为了筛选本周数据,WEEKDAY法简单直接;若为了生成“年周-周一”标签或做周维度维度表,STR_TO_DATE组合更自解释。

五、常见坑与注意事项

第一个坑是格式符混用。%Y是普通年份,%X是ISO年份,在跨年那一周两者可能不同。例如2023年12月31日是周日,按ISO算它属于2024年第01周,%X会返回2024,而%Y返回2023。如果错用%Y配合%V,会得到错误年份的周一。

第二个坑是会话语言或模式影响。STR_TO_DATE对格式不匹配会返回NULL,所以要确保CONCAT出来的字符串严格符合'%X-%V-%w'。建议在存储过程里先SELECT测试一周边界日期(如每年1月1日、12月31日)再上线。

方法优点缺点
STR_TO_DATE + DATE_FORMAT语义清晰,易对齐ISO周涉及字符串转换,稍复杂
WEEKDAY + DATE_SUB写法简单,性能好跨年周语义需自行验证

六、在查询中实际使用

假设有一张订单表orders,字段order_time为datetime,要统计本周一到现在的订单额:

SELECT SUM(amount) AS week_amount
FROM orders
WHERE order_time >= STR_TO_DATE(
  CONCAT(DATE_FORMAT(CURDATE(), '%X-%V'), '-1'),
  '%X-%V-%w'
);

这里用到的比较是直接DATE对DATETIME,MySQL会做隐式转换且能走order_time上的索引前缀(若查询条件为大于等于某日期)。比起在应用层算好周一再传参,纯SQL写法更方便复用,也方便后续改成存储函数。

如果需要频繁使用,可以封装成函数:

CREATE FUNCTION get_monday(d DATE)
RETURNS DATE
DETERMINISTIC
BEGIN
  RETURN STR_TO_DATE(
    CONCAT(DATE_FORMAT(d, '%X-%V'), '-1'),
    '%X-%V-%w'
  );
END;

之后直接SELECT get_monday(CURDATE())即可。注意函数里用了DETERMINISTIC,因为相同输入日期永远返回相同周一,利于优化器缓存。

七、小结

利用STR_TO_DATE与DATE_FORMAT组合获取本周一,本质是把“年周”语义显式表达出来,再解析为日期。它比单纯天数相减更贴合ISO周规则,尤其适合跨年报表与周维度建模。掌握%X、%V、%w的差异,就能灵活写出稳定的周起始日SQL,减少数据归类的偏差。

MySQLSTR_TO_DATEDATE_FORMAT修改时间:2026-08-06 20:57:15

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。