declare
@date datetime
set @date='1/4/13'
select DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0))
7 个回答
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 datepart(dw,@date) = 7 then dateadd(day,-1,@date)
else @date END)
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)。
月的最后一天
0 人赞同
我知道这不是最直观、最有效、最简单的方法。但是,这是我找到每月最后一个工作日的解决方案......
declare @date datetime, @lastDate datetime, @lastWeekDay datetime
set @date='05/4/2014';
set @lastDate = (SELECT DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0)));
declare @dayOfWeek INT = (SELECT DATEDIFF(dd, 0, @lastDate) % 7);
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;
0 人赞同
这个问题比它应该的要难得多。我曾用datename ,但只是因为我知道我使用的所有系统都会被配置为英语作为默认语言。如果没有这个假设,你就必须使用datepart(dw, ... ,而且你还必须担心SET DATEFIRST 。我还假设 "工作日 "是指 "星期一、星期二、星期三、星期四、星期五",而不包括星期六和星期日。(或者TFIG适用于全球?)
因此,通过我的方法,我们从你所拥有的开始。
DECLARE
@Date datetime
,@BOM datetime
SET @Date = '5/4/14'
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)
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)
任何或所有上述情况都可以而且应该被 "串联 "成一个单一的语句或查询(或者,最好是一个函数);如果你能安全地对你的安装语言和/或一周的第一天做出假设,你就可以进一步缩短它。
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)))
0 人赞同
declare @date datetime ='1/4/19'
select datename(dw, DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @date) + 1, 0)))
这将为你提供该月最后一天的日期名称。