2011-09-07 116 views
13

在SQL Server 2008中的isoweek可以用這個發現:Isoweek在SQL Server 2005

SELECT datepart(iso_week, getdate()) 

的SQL Server 2008之前沒有內置功能來找到isoweek。

我一直在尋找一個好的語法來找到一個用戶定義的SQL Server 2005的iso_week。我發現了很多的解決方案。不喜歡我發現的任何解決方案,其中大多數都沒有工作,而且時間太長。

由於問題很老,我預計這個問題已經耗盡,找到了最好的解決方案。雖然我找不到一個好方法。

我寫了一個解決方案,我將在稍後發佈。但在此之前,我想確保沒有其他人能夠匹配我寫的解決方案。

我希望能獲得自學者徽章。我敦促人們爲這個古老的問題尋找最好的答案。

我會在給人們找到一個好的解決方案的機會後發佈我的答案。

+0

除了星期數之外,重要的是包含ISO星期年,因爲它可以與正常日期年份不同。這似乎是不平凡的。 –

+0

@MicheldeRuiter鏈接到iso_year [這裏](http://stackoverflow.com/questions/22829604/what-is-iso-year-in-sql-server/22830524#22830524) –

+0

我已經找到你的答案了,很好讓其他讀者意識到。 –

回答

12

以下是一種與您的類似的方法,因爲它也依賴於本週的週四。但最終它會以不同的方式使用日期。

  1. 獲取此(星期四)星期四的日期。

    您自己的解決方案使用已知星期四的硬編碼日期。

    SELECT Th = DATEADD(DAY, 3 - (DATEPART(WEEKDAY, @date) + @@DATEFIRST - 2) % 7, @date) 
    

    (我沒有掙扎太多了正確的公式,因爲它是already known我)

  2. 獲取週四的一天:另外,本週的週四可能與@@DATEFIRST的幫助下找到今年:

    SELECT DY = DATEPART(DAYOFYEAR, Th) 
    
  3. 用數字找出這樣的一週:

    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; 
+0

+1 awsome,我花了一段時間才意識到你在做什麼,到目前爲止我認爲你是在作弊,爲什麼我沒有想到這一點。我將我們的答案結合到一個非常簡短的緊湊型解 –

+0

你真的應該得到這個解決方案,良好的工作夥伴的榮譽。 –

+0

非常感謝! –

34

有一個鏈接這裏等較早嘗試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的代碼片段。):

查找所選日期

dateadd(week, datediff(day, 0, @date)/7, 3) 

的平日4查找isoyear - 平日中的第4周總是與當週的同一年相同

datediff(yy, 0, day4) 

當添加3天的isoyear的第一天isoyear的第一isoweek的隨機一天發現

dateadd(yy, datediff(yy, 0, day4),3) 

找到isoyear

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

的第一isoweek的相對周尋找週一減去一週的週四第一isoweek結果isoyear

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

的第一isoweek的第一天之前4天知道的T第一個星期四他在第一個isoweek 和選定周的第一個星期四之前的一週, 使得計算一週相當容易,兩個日期的工作日都是星期四之後哪個設置日期第一次沒有關係。

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

+1。與此版本http://msdn.microsoft.com/en-us/library/ms186755.aspx相比,你的更好,因爲它不依賴'set datefirst 1'。 –

+0

不錯!我喜歡你的'(n + 6)/ 7'比我的'(n - 1)/ 7 + 1'更好。如果可以的話,我會再次提高這一點。 –

+0

+1000明亮的配方減少。 –

1

哇!非常好的主題和解決方案,以避免使用「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 

將返回「2015-01」。

+1

我已經爲iso_year寫了一個簡單的腳本。 http://stackoverflow.com/questions/22829604/what-is-iso-year-in-sql-server/22830524#22830524 –

0

我需要類似的PowerQuery & PowerBI,並基於t-clausen.dk的迴應我能夠做出這個等式。它和他一樣,但使用PowerQuery語法。也爲0的DATEDIFF基準日爲1/1/1900在SQL但在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]數據引用日期列。