4

我一直在寻找一大段代码来找到本周的第一天,并且在任何地方我都能看到:

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号。

谁能告诉我这里发生了什么?我很难相信没有人指出这不起作用,所以我想知道我错过了什么。

4

4 回答 4

6

正是它DATEDIFF返回了“不正确”的周差,最终导致错误的星期一。那是因为DATEDIFF(WEEK, ...)不尊重DATEFIRST设置,我假设您已设置为 1(星期一),而是始终认为一周交叉是从星期六到星期日,或者换句话说,它无条件地认为星期日到在这种情况下是一周的第一天。

至于对此的解释到目前为止我还没有找到官方的解释,但我相信这一定与DATEDIFF作为 SQL Server 始终视为确定性的函数之一有关。显然,如果DATEDIFF(WEEK, ...)依赖于DATEFIRST,它就不再被认为确定性的,我只能猜测 SQL Server 的开发人员并不是想要它。

为了找到一周中的第一天,我会(而且实际上经常这样做)使用@Jasmina Shevchenko 回答中的第一个建议:

DATEADD(DAY, 1 - DATEPART(WEEKDAY, @Date), @Date)

DATEPART确实尊重DATEFIRST设置,并且(很可能因此)它不在始终确定的函数列表中。

于 2013-05-15T10:21:32.103 回答
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
于 2013-05-14T16:56:29.607 回答
2

SQL Server 有一个SET DATEFIRST函数可以让你告诉它一周的第一天应该是什么。SET DATEFIRST = 1 告诉它将星期一视为一周的第一天。您应该通过@@DATEFIRST 检查服务器的默认设置。或者您可以在查询开始时简单地更改它。

一些参考资料:

MSDN

类似问题

于 2013-05-14T18:04:04.077 回答
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] 进行测试

于 2015-09-03T13:58:05.193 回答