2015-11-30 27 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) 
; 
相关问题