我一直在寻找一大堆代码来找到本周的第一天,而且我看到的每个地方都看到了这个:
DATEADD(WK, DATEDIFF(WK,0,GETDATE()),0)
每个地方都说这是我正在寻找的代码。
这段代码的问题在于,如果你在星期天运行它,它会选择下一个星期一。
如果我跑:
SELECT GetDate() , DATEADD(WK, DATEDIFF(WK,0,GETDATE()),0)
今日(星期二)的结果:
2013-05-14 09:36:39.650................2013-05-13 00:00:00.000
这是正确的,它选择了13日星期一。
如果我跑:
SELECT GetDate()-1 , DATEADD(WK, DATEDIFF(WK,0,GETDATE()-1),0)
昨天(星期一)的结果:
2013-05-13 09:38:57.950................2013-05-13 00:00:00.000
这是正确的,它选择了13日星期一。
如果我跑:
SELECT GetDate()-2 , DATEADD(WK, DATEDIFF(WK,0,GETDATE()-2),0)
12日(星期日)的结果:
2013-05-12 09:40:14.817................2013-05-13 00:00:00.000
这是不正确的,它选择在13日星期一选择上一个星期一,即6日。
有谁可以照亮我这里发生了什么?我发现很难相信没有人指出这不起作用,所以我想知道我错过了什么。
答案 0 :(得分:6)
DATEDIFF
返回周数的“不正确”差异,最终导致错误的星期一。这是因为DATEDIFF(WEEK, ...)
不尊重DATEFIRST
设置,我假设您设置为1(星期一),而是始终认为星期六从星期六到星期日,或者换句话说,无条件在此上下文中将星期日视为一周的第一天。
至于 的解释,到目前为止我还没有找到正式的,但我相信这必须与DATEDIFF
函数有关。这些SQL Server视为always deterministic。显然,如果DATEDIFF(WEEK, ...)
依赖于DATEFIRST
,则不能再将其视为始终确定性,我只能猜测不是SQL Server的开发人员想要它。
要找到一周中某天的第一天,我会(实际上经常会)使用@Jasmina Shevchenko's answer中的第一个建议:
DATEADD(DAY, 1 - DATEPART(WEEKDAY, @Date), @Date)
DATEPART
确实尊重DATEFIRST
设置,并且(最有可能的结果)始终确定性功能列表中没有
答案 1 :(得分:4)
试试这个 -
SET DATEFIRST 1
DECLARE @Date DATETIME
SELECT @Date = GETDATE()
SELECT CAST(DATEADD(DAY, 1 - DATEPART(WEEKDAY, @Date), @Date) AS DATE)
SELECT CAST(@Date - 2 AS DATE), CAST(DATEADD(WK, DATEDIFF(WK, 0, @Date-2), 0) AS DATE)
结果:
---------- ----------
2013-05-12 2013-05-13
答案 2 :(得分:2)
SQL Server具有SET DATEFIRST
功能,可让您告诉它一周的第一天应该是什么。 SET DATEFIRST = 1告诉它将星期一视为一周的第一天。您应该通过@@ DATEFIRST检查服务器的默认设置。或者您可以在查询开始时更改它。
一些参考文献:
答案 3 :(得分:0)
这对我来说就像一个魅力:
将moday设置为一周的第一天而不更改DATEFIRST变量:
-- FirstDayWeek
select dateadd(dd,(datepart(dw, case datepart(dw, [yourDate]) when 1 then dateadd(dd,-1,[yourDate]) else [yourDate] end) * -1) + 2, case datepart(dw, [yourDate]) when 1 then dateadd(dd,-1,[yourDate]) else [yourDate] end) as FirstDayWeek;
-- LastDayWeek
select dateadd(dd, (case datepart(dw, [yourDate]) when 1 then datepart(dw, dateadd(dd,-1,[yourDate])) else datepart(dw, [yourDate]) end * -1) + 8, case datepart(dw, [yourDate]) when 1 then dateadd(dd,-1,[yourDate]) else [yourDate] end) as LastDayWeek;
在不更改DATEFIRST变量的情况下将星期日设置为一周的第一天
select convert(varchar(50), dateadd(dd, (datepart(dw, [yourDate]) * -1) + 2, [yourDate]), 103) as FirstDayWeek, convert(varchar(50), dateadd(dd, (datepart(dw, [yourDate]) * -1) + 8, [yourDate]), 103) as LastDayWeek;
您可以通过GETDATE()更改[yourDate]进行测试