要获取周列表,我只需运行此(在线找到):
SET DATEFIRST 7
;with DateCTE as
(
select cast('01/01/2017' as datetime) DateValue
union all
select DateValue + 1
from DateCTE
where DateValue + 1 < '1/1/2018'
)
Select
cast(CAST(DateValue AS CHAR(11)) AS DateTime) AS [FullDate],
DATEPART(wk, DateValue) AS WeekOfYear,
DATEPART(yy, DateValue) AS CalendarYear
from DateCTE
OPTION (MAXRECURSION 0)
显然,如果我设置 DATEFIRST = 1,那么它会得到不同的结果。
我需要比较一张表中的日期,而不使用表变量。这就是我想要实现的目标:
因此,我希望在两个 CTE 中看到相同的 365 天,
我想比较基于不同 DateFirsts 的 WeekOfYear。
我不知道如何有效地做到这一点。我只能让它工作,当我
- 创建表变量 1 并为 DateFirst7 运行 CTE
- 创建表变量 2 并为 DateFirst1 运行 CTE
这是低效的,我正在寻找一种更好的方法来做到这一点。
有一些事情不利于此 1. 我不知道如何在查询中设置 DateFirst。我只知道在cte之前怎么设置。2. 我想为此使用嵌套 CTE,但 OPTION (MAXRECURSION 0) 不适用于嵌套 CTE
这可能吗 - 使用 CTE 获得所需的结果?
我开始尝试修复 Max Vernon 的答案,以便它适用于任何一年,但最终采用了两种不同的方法。
方法 1. 聪明
在这种方法中,我直接从一年中第一个基于星期日的星期日的偏移量计算基于星期日的周数。
一年的第一个星期日为基础的星期日可以这样得到:
您将 1 月 1 日作为工作日作为天数并从 1 月 1 日减去它,除非该日期是星期日,在这种情况下您什么都不减(这就是它的
… % 7
用途)。对于基于星期一的周数,上述公式的结果将始终是星期日,在这种情况下,它将是一年中第一个基于星期日的星期的星期日。在继续计算基于星期日的周数之前,这里是另一个将任何日期转换为同一年 1 月 1 日的公式:
基本上,获取日期并减去它的 DAYOFYEAR 值并添加一天。
现在这里是一个查询,它使用 Max Vernon 的 CTE 集、上面的两个公式和另一个获取实际周数的公式:
方法二、利用系统漏洞
此方法完全不同,因为它依赖于 DATEDIFF 函数的内置特性。
您可能知道,设置 DATEFIRST 会影响 和 等函数的
DATEPART(WEEK)
结果DATEPART(WEEKDAY)
。与它们不同,DATEDIFF(WEEK)
不遵守 DATEFIRST 设置。它始终计算差异,就好像 DATEFIRST 设置为 7,即始终将周视为基于星期日的周。知道这一点后,您可以计算 1 月 1 日与同年任何日期之间的周差,加 1 并将其用作基于星期日的周数:
您可以模拟修改
DATEFIRST
设置,因为这是一个众所周知的公式,您只需更改一周的第一天。结果的前几周:
边缘案例的乐趣。Max 的解决方案适用于 2017 年,因为 2017 年是从星期日开始的。如果您扩大日期范围,您会发现从星期日开始的年份都可以。然而,如果一年从一周中的任何一天开始,第一个星期日之前的部分周将始终显示为第 0 周。一些企业可能希望它是第 0 周(因为它是部分周),或前一个星期日的一部分年,或其他 - 然而,星期一日期的部分周是第 1 周,而不是第 0 周,所以我们有一个差异。
我看到解决它的最简单方法是检查这一年是否从星期日开始。如果是,则使用 Max 的原始代码
WeekOfYearStartingSunday
;如果没有,只需在他拥有的基础上加一个:这是前六年的第一天和最后一天(年份从除星期四以外的每一天开始——由于闰年,它会走得更远):