Isoweek在SQL Server 2005中

t-c*_*.dk 14 t-sql sql-server-2005

在SQL Server 2008中可以找到isoweek:

SELECT datepart(iso_week, getdate())
Run Code Online (Sandbox Code Playgroud)

在SQL Server 2008之前,没有内置函数可以找到isoweek.

我一直在寻找一个好的语法来寻找SQL Server 2005的用户定义的iso_week.我找到了不少解决方案.不喜欢我发现的任何解决方案,大多数都不起作用,而且它们太长了.

由于问题很严重,我预计这个问题已经耗尽,并找到了最佳解决方案.我虽然找不到好方法.

我写了一个解决方案,我将在稍后发布.但在此之前,我想确保没有其他人可以匹配我写的解决方案.

我希望能获得自学者徽章.我敦促人们为这个古老的问题找到最好的答案.

在让人们有机会找到一个好的解决方案后,我会发布我的答案.

t-c*_*.dk 36

其他早期尝试有一个链接http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=60510

这是该函数的OLD代码

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
Run Code Online (Sandbox Code Playgroud)

在将@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
Run Code Online (Sandbox Code Playgroud)

旧代码的解释(不解释新代码.它是来自我的代码和AndriyM代码的片段):

查找所选日期的工作日4

dateadd(week, datediff(day, 0, @date)/7, 3) 
Run Code Online (Sandbox Code Playgroud)

找到isoyear - 工作日的一年4周总是与那周的同年相同

datediff(yy, 0, day4)
Run Code Online (Sandbox Code Playgroud)

当在isoyear的第一天添加3天时,发现isoyear的第一个isoweek的随机日

dateadd(yy, datediff(yy, 0, day4),3)
Run Code Online (Sandbox Code Playgroud)

找到isoyear的第一个isoweek的相对周

datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7
Run Code Online (Sandbox Code Playgroud)

找到第一个isoweek的星期一减去4天的结果是在第一个isoweek的第一天之前的星期四的星期四

dateadd(ww, datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7,-4)
Run Code Online (Sandbox Code Playgroud)

知道了一周的第一个星期四的选择一周的第一isoweek和第一个星期四之前,使得它很容易计算的一周,它并不重要的设置DATEFIRST从此两个日期的工作日是星期四.

datediff(ww, dateadd(ww, datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7,-4),day4)
Run Code Online (Sandbox Code Playgroud)


And*_*y M 13

这是一种类似于你的方法,因为它也依赖于本周的周四.但最终它以不同的方式使用日期.

  1. 获取本周(ISO)周的日期.

    您自己的解决方案使用已知周四的硬编码日期.或者,本周的周四可以在以下帮助下找到@@DATEFIRST:

    SELECT Th = DATEADD(DAY, 3 - (DATEPART(WEEKDAY, @date) + @@DATEFIRST - 2) % 7, @date)
    
    Run Code Online (Sandbox Code Playgroud)

    (我没有为正确的配方而苦苦挣扎,因为我已经知道了.)

  2. 获取周四的一天:

    SELECT DY = DATEPART(DAYOFYEAR, Th)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用这个数字找出这样的一周:

    SELECT ISOWeek = (DY - 1) / 7 + 1
    
    Run Code Online (Sandbox Code Playgroud)

以下是单个语句中的上述计算:

SELECT ISOWeek = (DATEPART(DAYOFYEAR, Th) - 1) / 7 + 1
FROM (
  SELECT Th = DATEADD(DAY, 3 - (DATEPART(WEEKDAY, @date) + @@DATEFIRST - 2) % 7, @date)
) s;
Run Code Online (Sandbox Code Playgroud)