要回答为什么您得到星期一而不是星期日:
您要为日期0添加几周。什么是日期0?1900-01-01。1900-01-01是几号?星期一。因此,在您的代码中,您说的是,自1900年1月1日星期一以来已经过去了几周?我们称它为[n]。好的,现在将[n]个星期添加到1900年1月1日,星期一。您不必惊讶于这最终是星期一。DATEADD
不知道您要添加几周,而只是直到您到达一个星期日,才添加了7天,然后又添加了7天,...就像DATEDIFF
仅识别已越过的边界一样。例如,尽管有些人抱怨应该内置一些明智的逻辑来向上或向下取整,但它们都返回1:
SELECT DATEDIFF(YEAR, '2010-01-01', '2011-12-31');
SELECT DATEDIFF(YEAR, '2010-12-31', '2011-01-01');
回答如何获得星期日:
如果您想使用星期日,则选择不是星期一,而是星期日的基准日期。例如:
DECLARE @dt DATE = '1905-01-01';
SELECT [start_of_week] = DATEADD(WEEK, DATEDIFF(WEEK, @dt, CURRENT_TIMESTAMP), @dt);
如果您更改DATEFIRST
设置(或者代码正在为具有其他设置的用户运行),这不会中断-前提是无论当前设置如何,您仍然希望使用星期日。如果您希望这两个答案,牛仔舞,那么你应该使用一个功能不依赖于DATEFIRST
设置,例如,
SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP);
因此,如果将DATEFIRST
设置更改为星期一,星期二,那么您的行为将会改变。根据所需的行为,可以使用以下功能之一:
CREATE FUNCTION dbo.StartOfWeek1 -- always a Sunday
(
@d DATE
)
RETURNS DATE
AS
BEGIN
RETURN (SELECT DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @d), '19050101'));
END
GO
...要么...
CREATE FUNCTION dbo.StartOfWeek2 -- always the DATEFIRST weekday
(
@d DATE
)
RETURNS DATE
AS
BEGIN
RETURN (SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, @d), @d));
END
GO
现在,您有很多选择,但是哪个选择效果最好?如果会出现重大差异,我会感到惊讶,但我收集了到目前为止提供的所有答案,并通过两套测试对它们进行了测试-一套便宜而一套昂贵。我测量了客户端统计信息,因为在这里我看不到I / O或内存在性能中起作用(尽管根据功能的使用方式它们可能会起作用)。在我的测试中,结果是:
“便宜”分配查询:
Function - client processing time / wait time on server replies / total exec time
Gandarez - 330/2029/2359 - 0:23.6
me datefirst - 329/2123/2452 - 0:24.5
me Sunday - 357/2158/2515 - 0:25.2
trailmax - 364/2160/2524 - 0:25.2
Curt - 424/2202/2626 - 0:26.3
“昂贵”分配查询:
Function - client processing time / wait time on server replies / total exec time
Curt - 1003/134158/135054 - 2:15
Gandarez - 957/142919/143876 - 2:24
me Sunday - 932/166817/165885 - 2:47
me datefirst - 939/171698/172637 - 2:53
trailmax - 958/173174/174132 - 2:54
如果需要,我可以中继测试的详细信息-在此停止,因为这已经变得很漫长了。鉴于计算和内联代码的数量,看到Curt在高端市场上最快出现时,我感到有些惊讶。也许我会进行一些更彻底的测试并发布有关此事的博客...如果你们对我没有异议,请在其他地方发布您的函数。
(@@DATEFIRST + DATEPART(DW, @SomeDate)) % 7
无论@@datefirst
我认为如何,都保持不变。星期一=