在SQL Server 2008中可以找到isoweek:
SELECT datepart(iso_week, getdate())
在SQL Server 2008之前,没有内置函数可以找到isoweek。
我一直在寻找一个好的语法来寻找SQL Server 2005的用户定义的iso_week。我找到了不少解决方案。不喜欢我发现的任何解决方案,其中大多数都不起作用,而且它们太长了。
由于问题很严重,我预计这个问题已经耗尽,并且找到了最佳解决方案。我虽然找不到好方法。
我写了一个解决方案,我将在稍后发布。但在此之前,我想确保没有其他人可以匹配我写的解决方案。
我希望获得自学者徽章。我敦促人们为这个古老的问题找到最好的答案。
我会在让人们有机会找到一个好的解决方案之后发布我的答案。
答案 0 :(得分:36)
这里有其他早期尝试的链接http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=60510
这是函数的旧代码
CREATE function f_isoweek(@date datetime)
RETURNS INT
as
BEGIN
DECLARE @rv int
SELECT @rv = datediff(ww, dateadd(ww, datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7,-4),day4)
FROM (SELECT dateadd(ww, datediff(day, 0, @date)/7, 3) day4) a
RETURN @rv
END
在将@AndriyM的精彩回答与我自己的完美结合后,我们降到了1行。这是新代码。
CREATE function f_isoweek(@date datetime)
RETURNS INT
as
BEGIN
RETURN (datepart(DY, datediff(d, 0, @date) / 7 * 7 + 3)+6) / 7
-- replaced code for yet another improvement.
--RETURN (datepart(DY, dateadd(ww, datediff(d, 0, @date) / 7, 3))+6) / 7
END
旧代码的解释(不解释新代码。它是来自我的代码和AndriyM代码的片段):
查找所选日期的工作日4
dateadd(week, datediff(day, 0, @date)/7, 3)
找到同年 - 工作日的一年4周总是与那周的同年相同
datediff(yy, 0, day4)
当在isoyear的第一天添加3天时,发现了isoyear的第一个isoweek的随机日
dateadd(yy, datediff(yy, 0, day4),3)
找到isoyear的第一个isoweek的相对周
datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7
找到第一个isoweek的星期一减去4天的结果是在第一个isoweek的第一天之前的星期四的星期四
dateadd(ww, datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7,-4)
在第一个isoweek之前的一周的第一周知道 在选定的一周的第一个星期四, 因为计算一周是很容易的,所以从两个日期的工作日是星期四以来,设置datefirst的日期并不重要。
datediff(ww, dateadd(ww, datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7,-4),day4)
答案 1 :(得分:13)
这是一种类似于你的方法,因为它也依赖于本周的周四。但最终它以不同的方式使用日期。
获取本周(ISO)周的日期。
您自己的解决方案使用已知星期四的硬编码日期。或者,可以在@@DATEFIRST
:
SELECT Th = DATEADD(DAY, 3 - (DATEPART(WEEKDAY, @date) + @@DATEFIRST - 2) % 7, @date)
(我没有为正确的配方而苦苦挣扎,因为它对我来说是already known。)
获取周四的一天:
SELECT DY = DATEPART(DAYOFYEAR, Th)
使用该号码查找这样的一周:
SELECT ISOWeek = (DY - 1) / 7 + 1
以下是单一陈述中的上述计算:
SELECT ISOWeek = (DATEPART(DAYOFYEAR, Th) - 1) / 7 + 1
FROM (
SELECT Th = DATEADD(DAY, 3 - (DATEPART(WEEKDAY, @date) + @@DATEFIRST - 2) % 7, @date)
) s;
答案 2 :(得分:1)
哇!非常好的主题和解决方案,以避免使用"设置datefirst 1"。我只想添加一些东西。如果像我一样,你也希望以ISO周回归年份,例如" 2015-01"作为" 2015年,第01周和第34周,它可能对报告目的有用。从ISO周开始,可以与实际年份不同!以下是我与您的代码组合的方式。
DECLARE @Date AS DATETIME
SET @Date = '2014-12-31'
SELECT
CAST(CASE WHEN MONTH(@Date) = 1 AND Q.ISOweek > 50 THEN YEAR(@Date) - 1
WHEN MONTH(@Date) = 12 AND Q.ISOweek < 3 THEN YEAR(@Date) + 1
ELSE YEAR(@Date)
END
AS VARCHAR(4))
+ '-'
+ RIGHT('00' + CAST(Q.ISOweek AS NVARCHAR(2)), 2) AS ISOweek
FROM (SELECT (datepart(DY, datediff(d, 0, @Date) / 7 * 7 + 3) + 6) / 7 AS ISOweek) Q
将返回&#34; 2015-01&#34;。
答案 3 :(得分:0)
我需要类似的PowerQuery和amp; PowerBI并基于t-clausen.dk的响应,我能够制作出这个等式。它与他的工作方式相同,但使用的是PowerQuery语法。 DATEDIFF
为0的基准日期是SQL中的1/1/1900,但在PowerQuery中它是12/30/1899所以我用2而不是0。
ISO Week = Number.RoundDown((Date.DayOfYear(Date.From(Duration.Days(([Date]-Date.From(2))/7)*7+5))+6)/7)
我还需要ISO年份,所以我对ISO周计算进行了调整,得出了:
ISO Year = Date.Year(Date.From(Duration.Days(([Date]-Date.From(2))/7)*7+3))
更改[Date]
以引用数据中的日期列。