我需要一个结果集,包括两个日期之间的周,年和所有周的开始日期。我需要它来匹配其他搜索结果到周。由于报告将持续一年多,我需要它来匹配日历。
我们在欧洲,所以星期几在星期一开始。 我通过JDBC连接使用SQL Server。我不能使用压延表。
我遇到过各种各样的解决方案,但没有一个能满足我的需求。这是我需要的那种列表,但不知何故结果不正确。我找不到我的错误:
selenium
我用过--SET DATEFIRST 1;确保星期一星期几开始。
结果如下:
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);
问题很明显。 2010年还没有53周,第1周也没了。 这也适用于其他年份。只有2015年有53周。
(注意:在iso周(欧洲),2010年仅有52周,请参阅wiki:https://en.wikipedia.org/wiki/ISO_week_date)
在400年周期中接下来的71年(当前增加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,296,303,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周)
任何关于第1周的问题或为什么有这么多年的53(这是错误的)?
答案 0 :(得分:1)
在DATEPART
中使用iso_week
:
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
强>
您还可以考虑使用tally table
更改递归CTE。
答案 1 :(得分:1)
您在2010年看到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)
以下是今年年初的结果:
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个星期。
现在,为了回答你为什么没有看到2011年Week 1
价值的问题,让我们来看看那一年如何结束:
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-01-03
之前选择新的日期,因此它会有效地跳过2011年第一周的日期,并以Week 2
开头。
答案 2 :(得分:0)
SQL Server正在使用与Outlook匹配的标准周数(而53个声音奇怪,它是有效的)。
当然,您可以随时创建自己的自定义周数。您需要做的就是选择一个星期一开始并计算您要分配的星期数。然后,您的CTE可以增加其自己的周数,每当年度变化时重置为1。但即便如此,这将在第53周返回(2012年12月31日是星期一,使其成为当年的第53周,即使本周剩余的时间是在2013年)。
值得一提;您的周数不太可能与其他系统/流程相匹配。这可能会导致你的问题进一步发展。
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)
;