如何使用SQL查找当月的最后一个工作日

时间:2014-01-10 21:21:24

标签: sql sql-server-2008

如果使用SQL计算日期,我如何计算当前月份的最后一个工作日?

我能够获得当月的最后一天,但不确定如何以编程方式执行上一个工作日。

我不想生成日历查找表。

这是我正在使用的月份代码的最后一天:

declare @date datetime
set @date='1/4/13'
select DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0))

6 个答案:

答案 0 :(得分:2)

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

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;

答案 1 :(得分:2)

一个很好的解决方案:

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)

答案 2 :(得分:1)

这个比它应该的要困难得多。我使用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语句(我拒绝循环例程 - kludgy for database work)。

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
                   end
                  ,@BOM)

唉,这只适用于您的SQL实例配置了默认的“第一周的第一天”设置;这是通过PRINT @@datefirst检查的,其中7(默认值)= Sun,6 = Sat,依此类推。再一次,没有漂亮的算法表明自己,案例陈述变成了一团糟:

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
                   end
                  ,@BOM)

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

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

上述任何或所有内容都可以而且应该“连接”成一个语句或查询(或者更好的是一个函数);如果您可以安全地假设您的安装语言和/或一周的第一天,您可以进一步缩短它。

答案 3 :(得分: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))
            end
, 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)))
            end

答案 4 :(得分:0)

declare @date datetime ='1/4/19'
select datename(dw, DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0)))

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

答案 5 :(得分:0)

select case when datename(dw,(EOMONTH(getdate()))) ='Saturday' then day(EOMONTH(getdate())) -1
        when datename(dw,(EOMONTH(getdate()))) ='Sunday' then day(EOMONTH(getdate())) -2
        else day(EOMONTH(getdate())) end