我尝试按周对记录进行分组,将聚合日期存储为一周的第一天。但是,我用于四舍五入日期的标准技术似乎无法在几周内正常工作(尽管它可以在天、月、年、季度和我应用的任何其他时间范围内正常工作)。
这是 SQL:
select "start_of_week" = dateadd(week, datediff(week, 0, getdate()), 0);
这将返回 2011-08-22 00:00:00.000
,这是星期一,而不是星期日。选择 @@datefirst
返回 7
,这是星期日的代码,因此据我所知,服务器设置正确。
我可以通过将上面的代码更改为以下内容来轻松绕过这个问题:
select "start_of_week" = dateadd(week, datediff(week, 0, getdate()), -1);
但事实上我必须破例,这让我有点不安。另外,如果这是一个重复的问题,我们深表歉意。我发现了一些相关的问题,但没有一个专门解决这方面的问题。
最佳答案
回答为什么你得到星期一而不是星期日:
您要在日期 0 上添加周数。日期 0 是多少? 1900 年 1 月 1 日。 1900 年 1 月 1 日是什么日子?周一。所以在你的代码中你会说,自 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
设置(或者您的代码正在为具有不同设置的用户运行),则这不会中断 - 前提是无论当前设置如何,您仍然想要星期日。如果您想要 jive 这两个答案,那么您应该使用一个确实依赖于 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 成为高端最快的。也许我会进行一些更彻底的测试并在博客中介绍它...如果你们不反对我在其他地方发布您的函数。
关于sql-server - 在 SQL Server 中获取一周的第一天,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7168874/