Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 2005 SQLServer2005中的Isoweek_Sql Server 2005_Tsql - Fatal编程技术网

Sql server 2005 SQLServer2005中的Isoweek

Sql server 2005 SQLServer2005中的Isoweek,sql-server-2005,tsql,Sql Server 2005,Tsql,在SQL Server 2008中,可以通过以下内容找到isoweek: SELECT datepart(iso_week, getdate()) 在SQLServer2008之前,没有内置函数来查找isoweek 我一直在到处寻找一种好的语法,以便为SQLServer2005找到一个用户定义的iso_周。我找到了不少解决办法。我不喜欢我找到的任何解决方案,大多数都不起作用,而且太长了 由于这个问题已经很老了,我希望这个问题已经解决了,并且找到了最好的解决方案。但是我找不到一个好方法 我写了一

在SQL Server 2008中,可以通过以下内容找到isoweek:

SELECT datepart(iso_week, getdate())
在SQLServer2008之前,没有内置函数来查找isoweek

我一直在到处寻找一种好的语法,以便为SQLServer2005找到一个用户定义的iso_周。我找到了不少解决办法。我不喜欢我找到的任何解决方案,大多数都不起作用,而且太长了

由于这个问题已经很老了,我希望这个问题已经解决了,并且找到了最好的解决方案。但是我找不到一个好方法

我写了一个解决方案,稍后我会发布。但在我这么做之前,我想绝对确保没有其他人能够与我编写的解决方案相匹配

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


在给人们一个找到好的解决方案的机会之后,我将发布我的答案。

这里有一个链接,供其他早期尝试使用

这是函数的旧代码

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的精彩回答和我自己的回答后,我们只剩下一行了。这是新代码

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)
将3天添加到isoyear的第一天时,会找到isoyear的第一个isoweek的随机日期

dateadd(yy, datediff(yy, 0, day4),3)
查找isoyear的第一个isoweek的相对周

datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7
dateadd(ww, datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7,-4)
查找第一个ISO周的星期一减去4天,结果是在ISO年第一个ISO周的第一天之前的一周的星期四

datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7
dateadd(ww, datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7,-4)
在第一周之前知道一周的第一个星期四 和选定周的第一个星期四, 这使得计算一周变得非常容易,因为两个日期的工作日都是周四,所以datefirst的设置并不重要

datediff(ww, dateadd(ww, datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7,-4),day4)

这里有一个类似于你的方法,它也依赖于本周的星期四。但最终它用不同的日期

  • 获取本(ISO)周的星期四的日期

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

    SELECT Th = DATEADD(DAY, 3 - (DATEPART(WEEKDAY, @date) + @@DATEFIRST - 2) % 7, @date)
    
    (对于正确的配方,我没有太多的挣扎,因为它对我来说很重要。)

  • 获得一年中的星期四:

    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;
    

    哇!非常好的主题和解决方案,避免使用“set datefirst 1”。我只是想补充一点。如果像我一样,您也希望以ISO周返回年份,如“2015-01”作为“2015年,第01周”,这可能有助于报告目的。由于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
    
    将@Date声明为DATETIME
    设置日期='2014-12-31'
    挑选
    铸造(当月份(@Date)=1,Q.ISOweek>50时,则年份(@Date)-1
    当月份(@Date)=12且Q.ISOweek<3时,则年份(@Date)+1
    年份(@日期)
    结束
    作为VARCHAR(4))
    + '-'
    +右图('00'+演员阵容(Q.ISOweek为NVARCHAR(2)),2)为ISOweek
    FROM(选择(datepart(DY,datediff(d,0,@Date)/7*7+3)+6)/7作为ISOweek)Q
    

    将返回“2015-01”。

    我需要类似于PowerQuery和PowerBI的东西,并且基于t-clausen。dk的回答,我能够得出这个等式。它的工作原理与his相同,但使用PowerQuery语法。此外,0的
    DATEDIFF
    的基准日期在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]
    以引用数据中的日期列。

    +1。与此版本相比,您的版本更加丰富,因为它不依赖于
    set datefirst 1
    。很好!我喜欢你的
    (n+6)/7
    胜过我的
    (n-1)/7+1
    。如果可以的话,我会再次投票。如果我想让我的一周从周日开始呢?@Martin iso weeks不从周日开始这个公式太棒了。非常感谢+我花了一些时间才意识到你在做什么,到目前为止我认为你在作弊,为什么我没有想到这一点。我把我们的答案组合成一个非常简短的解决方案。嗨@AndriyM你可能是少数几个能欣赏的人之一——想象一下,一周8天,用同样的方法logic@t-克劳森:仍然在搞清楚逻辑的所有细节,但那是难以置信的。谢谢分享!我应该警告你,我为code golf提供的一些答案不容易理解understand@t-克劳森:没关系。当我听不懂他们中的任何一个时,我知道该向谁求助:)干杯!我已经为iso_年写了一个简单的脚本。除了周数之外,还必须包括ISO周年,因为它可能不同于正常日期年。“这似乎很重要。”MicheldeRuiter链接到iso_year我已经在那里找到了你的答案,很好地让其他读者意识到了这一点。