为什么 SQL Server dateadd datediff 在使用周时会这样

Why does SQL Server dateadd datediff behave behave this way when using weeks

当使用 dateadd/datdiff 技巧来舍入日期时,我总是得到非常可预测和易于理解的日期和月份结果。我现在是几周以来第一次使用它,并且遇到了一些我没想到的事情。
2015 年 7 月 19 日和 26 日似乎进入了我考虑的下一周。以下示例说明了第二列中的实际行为和第三列中的预期行为。我试图了解为什么以及如何存在差异。

declare @n as table ([N] [int] )

insert into @n ( [N] ) values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15)
select n
,      dateadd(dd,n,'2015-jul-17')
,      dateadd(wk,datediff(wk,0,  dateadd(dd,n,'2015-jul-17')  ),0)
,      dateadd(dd,datediff(dd,0,  dateadd(dd,n,'2015-jul-17')  )/7*7,0)
from @n
order by n

这个日期舍入算法,翻译成英文,可以表述如下:

Add a number of [Time Unit] to the start of calendar (Day 0)

其中 [Time Unit] 是 Year/Month/Days/Hours 等..... 日历开始时间是 1900/01/01 00:00:00 in T-SQL.

1900/01/01 是星期一。

因此您要将整周数加到星期一。因此,一周总是四舍五入到星期一。这会将 7/19 和 7/26(星期日)抛出到本周末。

问题是 DATEDIFF() 按周使用星期日而不是星期一作为一周的开始日。

一招是-1:

declare @n as table ([N] [int])
declare @start datetime = '1900-01-01'


insert into @n ( [N] ) values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15)
select n
,                           dateadd(dd,n,@start) as [Date]
,dateadd(wk,datediff(wk,0,  dateadd(dd,n,@start) -1 ),0) as [WeekStart (by WeekDiff)]
,dateadd(dd,datediff(dd,0,  dateadd(dd,n,@start)    )/7*7,0) as [WeekStart (by DayDiff)]
,           datediff(wk,0,  dateadd(dd,n,@start)) [WeekDiff]
from @n
order by n

Is it possible to set start of week for T-SQL DATEDIFF function?

编辑

DATEPART(WEEKDAY)SET DATEFIRST 1

结合使用
SET DATEFIRST 1

;with dates(value) as (select convert(date, dateadd(dd,n,@start)) from @n)
select *, DATEADD(Day, -DATEPART(WEEKDAY, value) + 1, value) from dates