注意: 任何以假设年份为 2011 年开始的答案都可以采用静态的第一个日期,即在下面的最后一个查询中将 @firstMon 替换为静态日期 '20101227 '。
SET DATEFIRST 1
declare @targetYear int
declare @targetWeek int
select @targetYear = 2011, @targetWeek = 23
declare @firstMon datetime
set @firstMon = dateadd(d,1-datepart(dw, right(@targetYear,4)+'0101'),right(@targetYear,4)+'0101')
select
MonOfTargetWeek = dateadd(week, @targetWeek-1, @firstMon),
SunOfTargetWeek = dateadd(week, @targetWeek-1, @firstMon+6)
以及真正的最终查询 - 当它在该周不存在时返回 NULL 的 Mon/Sun,例如partial-week-one 的 Mon 或 partial-week-53 的 Sun
;with tmp(Mon, Sun) as (
select
MonOfTargetWeek = dateadd(week, @targetWeek-1, @firstMon),
SunOfTargetWeek = dateadd(week, @targetWeek-1, @firstMon+6)
)
select
RealMonday = case when Year(Mon)=@targetYear then Mon end,
RealSunday = case when Year(Sun)=@targetYear then Sun end
from tmp
对于 GBN 声称这个答案是错误的(在他的答案内),我在正确性证明下方提交
我已经把代码变成了一个函数。
CREATE function dbo.getMonSunForWeek(@targetYear int, @targetWeek int)
returns table as return
with pre(firstMon) as (
select dateadd(d,1-datepart(dw, right(@targetYear,4)+'0101'),right(@targetYear,4)+'0101'))
, tmp(Mon, Sun) as (
select
dateadd(week, @targetWeek-1, firstMon),
dateadd(week, @targetWeek-1, firstMon+6)
from pre
)
select
Mon, Sun,
RealMonday = case when Year(Mon)=@targetYear then Mon end,
RealSunday = case when Year(Sun)=@targetYear then Sun end
from tmp
GO
在下面我展示了从 1950 年到 2047 年的整个年和周 (1-53) 范围。在 每一个情况下,当星期一/星期日已确定时,使用DATEPART(week) 向后工作,SQL Server 同意函数中的星期编号。
set datefirst 1;
select
[Year] = years.number,
[Week] = weeks.number,
[Mon] = fun.realmonday,
[Sun] = fun.realsunday,
[WeekX] = isnull(datepart(week, fun.realmonday), datepart(week, fun.realsunday)),
[MonX] = fun.Mon,
[SunX] = fun.Sun
from master..spt_values years
inner join master..spt_values weeks on weeks.type='P' and weeks.number between 1 and 53
cross apply dbo.getMonSunForWeek(years.number, weeks.number) fun
where years.type='P' and years.number between 1950 and 2047
order by [year], [Week]
2005-2006 年转换前后的输出
when including prior/next year
Year Week Mon-of-week Sun-of-week datepart(week) Mon -and- Sun
2005 52 2005-12-19 2005-12-25 52 2005-12-19 2005-12-25
2005 53 2005-12-26 NULL 53 2005-12-26 2006-01-01
2006 1 NULL 2006-01-01 1 2005-12-26 2006-01-01
2006 2 2006-01-02 2006-01-08 2 2006-01-02 2006-01-08