如果使用SQL计算日期,我如何计算当前月份的最后一个工作日?
我能够获得当月的最后一天,但不确定如何以编程方式执行上一个工作日。
我不想生成日历查找表。
这是我正在使用的月份代码的最后一天:
declare @date datetime
set @date='1/4/13'
select DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0))
答案 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