2015-11-30 29 views
1

我需要weeknumers的結果集,year和兩個日期之間的所有星期的startdate。我需要它來匹配其他搜索結果。由於報告將跨越一年,我需要它來匹配日曆。需要兩個日期之間的週數列表

我們在歐洲,所以星期一開始。 我通過JDBC連接使用SQL Server。我無法使用calander表。

我遇到過各種解決方案,但沒有一個只是我需要的。這是我需要的那種清單,但不知何故結果是不正確的。我找不到我的錯誤:

WITH mycte AS 
(
SELECT DATEADD(ww, DATEDIFF(ww,0,CAST('2010-12-01' AS DATETIME)), 0) DateValue 
UNION ALL 
SELECT DateValue + 7 
FROM mycte 
WHERE DateValue + 7 < '2016-12-31' 
) 

SELECT DATEPART(wk, DateValue) as week, DATEPART(year, DateValue) as year, DateValue 
FROM mycte 
OPTION (MAXRECURSION 0); 

我用過--SET DATEFIRST 1;確保星期一開始。

結果是這樣的:

week  year  DateValue     
----------- ----------- ------------------------- 
49   2010  2010-11-29 00:00:00.0  
50   2010  2010-12-06 00:00:00.0  
51   2010  2010-12-13 00:00:00.0  
52   2010  2010-12-20 00:00:00.0  
53   2010  2010-12-27 00:00:00.0  
2   2011  2011-01-03 00:00:00.0  
3   2011  2011-01-10 00:00:00.0  
4   2011  2011-01-17 00:00:00.0  
5   2011  2011-01-24 00:00:00.0  
6   2011  2011-01-31 00:00:00.0 

的問題是顯而易見的。 2010年還沒有53周,第一週就沒了。 這也有其他年份。 2015年只有53周。

(注意:在ISO周(歐洲)有在2010年只有52個星期,看到維基:https://en.wikipedia.org/wiki/ISO_week_date

以下71年在一個400年的週期(增加2000當前 歲) 53周(閏年,2月29日強調), 年未列出有52周:004,009,015,020,026,032,037, 043,048,054,060,065,071,076 ,082,088,093,099,105,111,116, 122,128,133,139,144,150,156,161,167,172,178,184,189, 195,201,207,212,218,224 ,229,235,240,246,252,257,263,268, 274 ,280,285,291,296303,308,314,320,325,331,336,342,348,353 ,359,364,370,376,381,387,392,398.

日期是正確的,但。 2012-12-27是星期一,2011-01-03也是。 但是在歐洲,我們總是有一整週的時間(所以總有一週的週數爲1)

任何想法對第1周有什麼影響,或者爲什麼有這麼多年53(這是錯誤的)?

+1

你爲什麼假設53周的一年是錯誤的? 2010年1月1日和2日被認爲是在第1周內,1月3日(週日)從第2周開始。總共有53周。到2000年,共有54周。 – Siyual

+0

好吧,除了實際的數字(eurpean的東西),我們都同意他們應該是連續的,總是有一週。所以這是錯誤的。我也沒有任何東西,我在下面指出的@ lad2025看了iso周。所以在這個範圍內,只有2015年有53周。 – Jeroen

回答

1

使用iso_weekDATEPART

ISO 8601包括ISO周 - 日期系統,用於 周編號系統。每週都與週四發生的年份相關聯。 例如,2004年第1周(2004W01)從2003年12月29日星期一 運行到2004年1月4日星期日。一年中最高星期數可能是 52或53.這種編號方式通常用於歐洲 國家/地區,但其他地方很少見。

WITH mycte AS 
(
SELECT DATEADD(ww, DATEDIFF(ww,0,CAST('2010-12-01' AS DATETIME)), 0) DateValue 
UNION ALL 
SELECT DateValue + 7 
FROM mycte 
WHERE DateValue + 7 < '2016-12-31' 
) 
SELECT DATEPART(iso_week, DateValue) as week, DATEPART(year, DateValue) as year, 
     DateValue 
FROM mycte 
OPTION (MAXRECURSION 0); 

LiveDemo

您也可以考慮改變遞歸CTE與tally table

+0

啊,thx。這完全解決了它。 – Jeroen

1

你在2010年看到53周原因很簡單,因爲有53周在2010年

讓我們在幾個星期如何在這一年打破仔細一看:

Declare @FromDate Date = '2010-01-01', 
     @ToDate  Date = '2011-01-03' 

;With Date (Date) As 
(
    Select @FromDate Union All 
    Select DateAdd(Day, 1, Date) 
    From Date 
    Where Date < @ToDate 
) 
Select Date, DatePart(Week, Date) WeekNo, DateName(WeekDay, Date) WeekDay 
From Date 
Option (MaxRecursion 0) 

SQL Fiddle

這裏是年初是如何:

Date  WeekNo  WeekDay 
---------- ----------- ------------------------------ 
2010-01-01 1   Friday 
2010-01-02 1   Saturday 
2010-01-03 2   Sunday 
2010-01-04 2   Monday 
2010-01-05 2   Tuesday 
2010-01-06 2   Wednesday 
2010-01-07 2   Thursday 
2010-01-08 2   Friday 
2010-01-09 2   Saturday 
2010-01-10 3   Sunday 

自今年開始,在一週的中間,只有兩天Week 1。這導致這一年共有53周。

現在回答你爲什麼看不到一個Week 1值2011,讓我們來看看這一年是如何結束的問題:

Date  WeekNo  WeekDay 
---------- ----------- ------------------------------ 
2010-12-26 53   Sunday 
2010-12-27 53   Monday 
2010-12-28 53   Tuesday 
2010-12-29 53   Wednesday 
2010-12-30 53   Thursday 
2010-12-31 53   Friday 
2011-01-01 1   Saturday 
2011-01-02 2   Sunday 
2011-01-03 2   Monday 

你在7天爲單位選擇您的日期。你拉到2010年的最後日期是2010-12-27,這是準確的顯示在53周是但明年開始這一週內發生在星期六,使得週六2011年Week 1,與次日開始Week 2

由於您在星期一之前沒有選擇新的日期,所以它將有效地跳過2011年第一週的日期,並從Week 2開始。

+0

嗨,thx爲您的解釋,但我在歐洲,所以我們這樣做編號有點不同。 (請參閱我的帖子更新) – Jeroen

+0

根據年份發生變化的時間,無論您是在星期日還是星期一開始星期,都不會導致我的回答有任何不同。 – Siyual

0

SQL Server使用標準的週數,匹配與Outlook這(和而53聽起來很奇怪它是有效的)。

當然,你總是可以創建自定義的週數。所有你需要做的就是選擇一個週一開始,並計算你將分配的週數。然後,CTE可以增加自己的周計數,每次更改時重設爲1。但即使這樣也會在第53週迴歸(2012年12月31日是週一,即使本週剩下的時間在2013年,也是這一週的第53周)。

值得一提的;您的週數不可能與其他系統/流程的數據匹配。這可能會導致問題進一步惡化。

SET DATEFIRST 1; 

WITH [Week] AS 
    (
      SELECT 
       CAST('2010-11-29' AS DATE)  AS [Date], 
       48        AS WeekNumber 

     UNION ALL 

      SELECT 
       DATEADD(DAY, 7, [Date]) AS [Date], 
       CASE 
        -- Reset the week number count when the year changes. 
        WHEN YEAR([Date]) <> YEAR(DATEADD(DAY, 7, [Date])) THEN 1 
        ELSE WeekNumber + 1    
       END AS WeekNumber 
      FROM 
       [Week] 
      WHERE 
       [Date] < GETDATE() 
    ) 
SELECT 
    * 
FROM 
    [Week] 
OPTION 
    (MAXRECURSION 0) 
; 
相關問題