相关文章推荐
潇洒的茴香  ·  Date.prototype.toUTCSt ...·  3 月前    · 
道上混的饭盒  ·  Get-Date ...·  1 月前    · 
冷静的热带鱼  ·  【jdk1.8】LocalDateTime ...·  1 月前    · 
declare




    
 @date datetime
set @date='1/4/13'
select DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0))
    
sql
sql-server-2008
FistOfFury
FistOfFury
发布于 2014-01-11
7 个回答
John Welsh
John Welsh
发布于 2021-03-03
0 人赞同

相当巧妙的解决方案。

declare @date1 as date = '20130401'
declare @date as date= eomonth(@date1,0)
set @date = (select case
    when datepart(dw,@date) = 1 then dateadd(day,-2,@date) --when day is a sunday subtract 2 day to friday
    when datepart(dw,@date) = 7 then dateadd(day,-1,@date) --when day is a saturday subtract 1 day to friday
    else @date END)
    
Bojan Baros
Bojan Baros
发布于 2021-03-03
0 人赞同

我知道这已经很老了,但我在寻找一个单行本,并在这里找到了。 这是我想出的一个办法。

set DATEFIRST 1
declare @testDate datetime
select @testDate = '8/1/2016'
select dateadd(day, -(select max(dayCount) from (values (DATEPART(WEEKDAY, EOMONTH(@testDate)) - 5), (0 )) as allDays(dayCount)), EOMONTH(@testDate))

这只适用于SQL Server 2012及以上版本。

它是如何工作的。

  • 获取测试日期的最后一个日历日期
  • 获取一周中的哪一天,其中周一是1,周六是6,周日是7
  • 减去星期几,如果是负数,则将其设置为0。 实际上是一个max(0, day-of-the week - 5)。 这将使星期六为1,星期日为2。
  • 从一个月的最后一天中减去天数(如果是星期六则为1,如果是星期日则为2)。 月的最后一天
  • 我想如果你把@@DATEFIRST结合起来,你就几乎达到了。
    user2989408
    user2989408
    发布于 2021-03-03
    已采纳
    0 人赞同

    我知道这不是最直观、最有效、最简单的方法。但是,这是我找到每月最后一个工作日的解决方案......

    declare @date datetime, @lastDate datetime, @lastWeekDay datetime
    set @date='05/4/2014';--'1/1/2014'
    set @lastDate = (SELECT DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0)));
    /* @dayOfWeek represents -- 0-Monday through 7-Sunday */
    declare @dayOfWeek INT = (SELECT DATEDIFF(dd, 0, @lastDate) % 7);
    /* If last date is sat/sun substract 1 or 2 days from last date */
    set @lastWeekDay = (SELECT CASE WHEN @dayOfWeek = 5 THEN DATEADD(dd, -1, @lastDate)
                                   WHEN @dayOfWeek = 6 THEN DATEADD(dd, -2, @lastDate)
                                   ELSE @lastDate END)
    SELECT @lastWeekDay;
        
    Philip Kelley
    Philip Kelley
    发布于 2021-03-03
    0 人赞同

    这个问题比它应该的要难得多。我曾用datename ,但只是因为我知道我使用的所有系统都会被配置为英语作为默认语言。如果没有这个假设,你就必须使用datepart(dw, ... ,而且你还必须担心SET DATEFIRST 。我还假设 "工作日 "是指 "星期一、星期二、星期三、星期四、星期五",而不包括星期六和星期日。(或者TFIG适用于全球?)

    因此,通过我的方法,我们从你所拥有的开始。

    DECLARE
      @Date datetime
     ,@BOM  datetime
    --SET @Date = '1/4/14'  --  Should return Jan 31, 2013
    SET @Date = '5/4/14'  --  Should return May 30, 2014 (not May 31)
    SET @BOM  =  DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0)
    PRINT @BOM
    

    这将@BOM(月初)设置为@Date中的任何内容之后的第一个月的一天。(我把它分成多个语句,因为否则你必须在下面的代码中到处重复这个函数)。

    接下来,你必须从这一天 "往后移 "一天、两天或三天。如果BOM是星期一,-3就可以到前一个星期五;如果BOM是星期天,-2就可以到星期五;否则,-1就可以让你到一个工作日。根据datepart ,我想不出有什么好的算法可以产生-1/-2/-3的差价,所以我使用了一个case语句(我拒绝使用循环程序--对于数据库工作来说太笨拙了)。

    PRINT datepart(dw, @BOM)  --  To see what is is
    PRINT dateadd(dd, case
                        when datepart(dw, @BOM) = 2 then -3
                        when datepart(dw, @BOM) = 1 then -2
                        else -1
                      ,@BOM)
    

    唉,这只有在你的SQL实例配置了默认的 "一周的第一天 "设置时才有效;这可以通过PRINT @@datefirst ,其中7(默认)=太阳,6=星期六,以此类推。再一次,没有任何古怪的算法提示自己,case语句变成了一团糟。

    PRINT dateadd(dd, case
                        when @@datefirst = 7 and datepart(dw, @BOM) = 2 then -3
                        when @@datefirst = 7 and datepart(dw, @BOM) = 1 then -2
                        when @@datefirst = 6 and datepart(dw, @BOM) = 3 then -3
                        when @@datefirst = 6 and datepart(dw, @BOM) = 2 then -2
                        when @@datefirst = 5 and datepart(dw, @BOM) = 4 then -3
                        when @@datefirst = 5 and datepart(dw, @BOM) = 3 then -2
                        when @@datefirst = 4 and datepart(dw, @BOM) = 5 then -3
                        when @@datefirst = 4 and datepart(dw, @BOM) = 4 then -2
                        when @@datefirst = 3 and datepart(dw, @BOM) = 6 then -3
                        when @@datefirst = 3 and datepart(dw, @BOM) = 5 then -2
                        when @@datefirst = 2 and datepart(dw, @BOM) = 7 then -3
                        when @@datefirst = 2 and datepart(dw, @BOM) = 6 then -2
                        when @@datefirst = 1 and datepart(dw, @BOM) = 1 then -3
                        when @@datefirst = 1 and datepart(dw, @BOM) = 7 then -2
                        else -1
                      ,@BOM)
    

    丑陋,还是什么?循环结构也必须考虑到这一点。当然,如果你能依靠在你的SQL实例上始终使用相同的语言,那就简单多了。

    PRINT dateadd(dd, case
                        when datename(dw, @BOM) = 'Monday' then -3
                        when datename(dw, @BOM) = 'Sunday' then -2
                        else -1
                      ,@BOM)
    

    任何或所有上述情况都可以而且应该被 "串联 "成一个单一的语句或查询(或者,最好是一个函数);如果你能安全地对你的安装语言和/或一周的第一天做出假设,你就可以进一步缩短它。

    我喜欢这其中的解释和努力。 谢谢你这么做。 我认为使用用户2989408提供的Day Of Week #的不太啰嗦的查询对我的目的来说更容易使用。
    rhealitycheck
    rhealitycheck
    发布于 2021-03-03
    0 人赞同

    你可以尝试使用工作日函数,如

    select datename(dw, getdate())
    

    然后在你的查询中使用这个函数来得出该月的最后一个星期的日期

    这样你就可以得到这样的结果,而不必实际创建一个 "日期 "表

        declare @date datetime
    set @date='3/4/13'
    select case when datename(dw, DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0))) = 'Saturday'
                then DATEADD(d, -2, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0))
                when datename(dw, DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0))) = 'Sunday'
                then DATEADD(d, -3, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0))
                else DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0))
    , case when datename(dw, DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0))) = 'Saturday'
                then datename(dw, DATEADD(d, -2, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0)))
                when datename(dw, DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0))) = 'Sunday'
                then datename(dw, DATEADD(d, -3, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0)))
                else datename(dw, DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0)))
        
    你没有选择datepart(dw, @date) ,而不是选择返回一个字符串的,有什么特别原因吗?
    我个人认为,获取星期名称的字符串比试图记住哪一个int对应于星期的名称更有可读性,特别是在这种情况下,他只是试图排除星期六和星期日。但这只是我对结果显示的可读性的看法。
    绳子会不会只用英语?
    我相信它使用的是你所在的sql server的默认语言,所以你可能需要看一下文档来确认。
    Abdul Qadir Memon
    Abdul Qadir Memon
    发布于 2021-03-03
    0 人赞同
    declare @date datetime ='1/4/19'
    select datename(dw, DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0)))
    

    这将为你提供该月最后一天的日期名称。