我试图按周分组记录,将汇总日期存储为一周的第一天 . 但是,我用于舍入日期的标准技术似乎在几周内没有正常工作(尽管它确实存在了几天,几个月,几年,几个季度以及我应用它的任何其他时间范围) .
这是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);
但事实上,我必须做出这样的例外让我有点不安 . 此外,如果这是一个重复的问题,请道歉 . 我发现了一些相关问题,但没有一个专门解决这个问题 .
13 回答
To answer why you're getting a Monday and not a Sunday:
你说,自1900年1月1日星期一以来经过了多少个星期?我们称之为[n] . 好的,现在加上[n]周到1900年1月1日星期一 . 你不应该对这最终成为星期一感到惊讶 .
DATEADD
不知道你想要添加星期,但只有在你到达星期天之后,它只需要增加7天,然后再增加7天,......就像DATEDIFF
只能识别已经越过的边界 . 例如,这些都返回1,即使有些人抱怨应该有一些合理的逻辑来内聚或下移:To answer how to get a Sunday:
如果你想要一个星期天,那么选择一个不是星期一而是星期天的基准日期 . 例如:
如果您更改
DATEFIRST
设置(或者您的代码正在为具有不同设置的用户运行),这不会中断 - 前提是您仍然需要星期日,而不管当前设置如何 . 如果你想要这两个jive的答案,那么你应该使用一个依赖于DATEFIRST
设置的函数,例如因此,如果您将
DATEFIRST
设置更改为周一,周二,那么您的行为将会发生变化 . 根据您想要的行为,您可以使用以下功能之一:...要么...
现在,你有很多选择,但哪一个表现最好?如果会有任何重大差异,我会感到惊讶,但我收集到目前为止提供的所有答案,并通过两组测试运行 - 一个便宜,一个昂贵 . 我测量了客户端统计信息,因为我没有看到I / O或内存在这里的性能中起作用(尽管这些可能会起作用,具体取决于函数的使用方式) . 在我的测试中,结果如下:
“便宜”的分配查询:
“昂贵的”分配查询:
如果需要,我可以传递我的测试细节 - 在这里停下来,因为这已经变得非常冗长 . 考虑到计算和内联代码的数量,看到Curt在高端出现最快,我感到有些惊讶 . 也许我会进行一些更彻底的测试和博客...如果你们对我在其他地方发布你的功能没有任何异议 .
对于需要获得的这些:
星期一= 1,星期日= 7:
星期日= 1和星期六= 7:
上面有一个类似的例子,但由于双“%7”,它会慢得多 .
这对我很有用:
谷歌搜索这个脚本:
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=47307
对于那些需要在工作中得到答案并且DBA禁止创建功能的人,以下解决方案将起作用:
这给了那一周的开始 . 在这里,我假设星期日是几个星期的开始 . 如果您认为星期一是开始,您应该使用:
也许你需要这个:
要么
功能
由于朱利安日期0是星期一,所以只需将星期数添加到星期日,即-1 Eg之前的一天 . 选择dateadd(wk,datediff(wk,0,getdate()), - 1)
这是我的逻辑 . 将本周的第一周设置为星期一,然后计算给定日的星期几,然后使用DateAdd和Case I计算该星期一周一的日期 .
我对这里给出的任何答案都没有任何问题,但是我认为我的实现和理解要简单得多 . 我没有对它进行任何性能测试,但它应该是可以忽略的 .
所以我从日期作为整数存储在SQL服务器中的事实得出了我的答案,(我只讨论日期组件) . 如果你不这样做相信我,尝试这个SELECT CONVERT(INT,GETDATE()),反之亦然 .
现在知道这一点,你可以做一些很酷的数学方程式 . 你或许可以想出一个更好的,但这是我的 .
我遇到了类似的问题 . 鉴于约会,我想得到那个星期一的星期日 .
我使用了以下逻辑:在0-6范围内找到一周中的日期编号,然后从原始日期中减去该数字 .
我用过:DATEADD(白天, - (DATEPART(工作日))5%7)
由于DATEPRRT(工作日)返回1 =星期日... 7 =星期六,DATEPART(工作日,)5)%7返回0 =星期一... 6 =星期日 .
从原始日期减去这个天数给出了上一个星期一 . 一周的任何开始日都可以使用相同的技术 .
我发现这很简单有用 . 即使一周的第一天是星期日或星期一也能正常工作 .
DECLARE @BaseDate AS日期
SET @BaseDate = GETDATE()
DECLARE @FisrtDOW AS日期
SELECT @FirstDOW = DATEADD(d,DATEPART(WEEKDAY,@ BaseDate)* -1 1,@ BaseDate)
也许我在这里过度简化,可能就是这样,但这似乎对我有用 . 还没有遇到任何问题......