You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

给定日期所在月份首个周一的SQL查询是否有效?有无更优方案?

问题解答

原SQL语句不符合预期

你的SQL逻辑存在问题,它返回的是当月第一天之前最近的周一(可能属于上月),而非当月内的首个周一。举个实际例子:
假设给定日期是2024年3月15日,当月第一天是3月1日(周五,按你的配置DATEPART(WEEKDAY)返回5),代入计算后得到的是2024年2月26日(上月的周一),但3月的首个周一应该是3月4日。

问题出在:当当月第一天晚于周一(周二到周日)时,你的SQL会往回追溯周一,而不是在当月范围内往后找第一个周一。

更优的实现方式

根据你的星期配置(周日=0,周一=1),推荐两种直观的正确写法:

写法1:分步计算(可读性高)

先拿到当月第一天,再根据星期数判断调整:

DECLARE @targetDate DATE = '2024-03-15';
DECLARE @firstDayOfMonth DATE = DATEFROMPARTS(YEAR(@targetDate), MONTH(@targetDate), 1); -- 更直观的月初获取方式

SELECT
    CASE
        WHEN DATEPART(WEEKDAY, @firstDayOfMonth) = 1 THEN @firstDayOfMonth
        ELSE DATEADD(DAY, 8 - DATEPART(WEEKDAY, @firstDayOfMonth), @firstDayOfMonth)
    END AS FirstMondayOfMonth;

逻辑解释:

  • 若当月第一天就是周一(WEEKDAY=1),直接返回;
  • 若是其他日期,比如周五(WEEKDAY=5),8-5=3,加3天就得到当月第一个周一。

写法2:单语句简化版

如果不想用变量,也可以把逻辑合并成一条:

SELECT
    DATEADD(DAY,
        CASE DATEPART(WEEKDAY, DATEFROMPARTS(YEAR([DATE]), MONTH([DATE]), 1))
            WHEN 1 THEN 0
            ELSE 8 - DATEPART(WEEKDAY, DATEFROMPARTS(YEAR([DATE]), MONTH([DATE]), 1))
        END,
        DATEFROMPARTS(YEAR([DATE]), MONTH([DATE]), 1)
    ) AS FirstMondayOfMonth;

关于“没有月初函数”的疑问

SQL Server确实没有内置的FIRSTDAYOFMONTH函数,但有两种简洁的替代方式:

  1. 用DATEFROMPARTS(YEAR(@date), MONTH(@date), 1)(SQL Server 2012+支持),语法最直观;
  2. 就是你用的DATEADD(DAY, 1, EOMONTH(DATEADD(MONTH, -1, @date))),兼容性更好。

内容的提问来源于stack exchange,提问作者J. Mini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 13:25:38