给定周数,返回 T-SQL 中一周的第一天
Posted
技术标签:
【中文标题】给定周数,返回 T-SQL 中一周的第一天【英文标题】:Given a Week Number, Return the First Day of the Week in T-SQL 【发布时间】:2016-07-27 14:30:07 【问题描述】:这会给我一个基于日期的星期数:
SELECT DATEPART(wk, '7/27/2016') AS [Week]
例如,返回 31。
现在,我需要做的是找到该周的第一天,并以短日期格式返回。例如:
Given Week: 31
Return First Day of Week: July 24
或者
Given Week: 52
Return First Day of Week: Dec 25
我相信一周的默认第一天是星期日,这就是我需要的日期。
我在这里看到了几篇接近的帖子,但没有一个能让我一路走好。
谢谢!
【问题讨论】:
如何定义一周的“第一”天?有些使用星期日,有些使用星期一。 好问题。我的意思是要说明这一点。我认为默认是星期日,这就是我想要的。 可能重复:***.com/questions/7168874/… @jpw,我看到了那个。但是这个问题,就像我所看到的一样,假设你从约会开始。我需要以数字 (31) 开头并返回一个日期。 那么您真正需要的是一年中给定一周中的星期日日期(“first”在这种情况下太容易使用了),对吧? 【参考方案1】:我帮助从内到外阅读此内容。我添加了编号的 cmets 来提供帮助。
declare @weekNum int;set @weeknum = 52;
select
-- 3. Add number of weeks
dateadd(wk, @weekNum,
--2. first day of week 0 for that year (may belong to previous year)
dateadd(ww, datediff(wk, 0,
--1. First date of the year (week 0)
dateadd(YEAR, datediff(year,0, getDate()),0)
),-1) -- -1 here because 1900-01-01 (date 0) was a Monday, and adding weeks to a Monday results in a Monday.
)
我们可以将第二步和第三步结合起来,因为它们都增加了周数:
declare @weekNum int;set @weeknum = 52;
select
--2. first day of week 0 for that year (may belong to previous year) + number of weeks
dateadd(ww, @weekNum + datediff(wk, 0,
--1. First date of the year (week 0)
dateadd(YEAR, datediff(year,0, getDate()),0)
),-1) -- -1 here because 1900-01-01 (day 0) was a Monday. Adding weeks to a Monday results in a Monday
另外,我认为您在第 31 周的示例提前了一周。您可以像这样查看全年的完整集:
with weeks as
(
select top 52 row_number() over (order by object_id) as wk from sys.objects
)
select wk,
--2. first day of week 0 for that year (may belong to previous year) + number of weeks
dateadd(ww, wk + datediff(wk, 0,
--1. First date of the year (week 0)
dateadd(YEAR, datediff(year,0, getDate()),0)
),-1) -- -1 here because 1900-01-01 (day 0) was a Monday. Adding weeks to a Monday results in a Monday
from weeks
【讨论】:
好吧,这里有些奇怪。 SELECT DATEPART(wk, '7/27/2016') 返回 31。但是,如果我将 31 放回您的查询中,我会得到 2016 年 7 月 31 日。给定一个日期,该日期所在一周的第一天不能晚于该日期。 问题是一年的第一天不是星期天。你想怎么解释呢?你想展示去年的一天吗?第 1 周的结果应该是 2016-01-03 还是 2015-12-27?如果您对此进行更改,它将一切向前移动,包括第 52 周(您要允许第 53 周吗?)。 我明白你的意思。我们现在拥有的是从 1 月 3 日开始的第 1 周,忽略了 1 月 1 日和 1 月 2 日。我需要包括这些日期。所以,我们最好从 2015 年 12 月 27 日开始第 1 周。 很容易将 -1 添加到第 num 周,但请记住,这现在将更改您问题中第 52 周的结果,在年底时会出现部分第 53 周。我还想在周日开始的一年内对此进行测试。如果 1 月 1 日是星期天,您可能还需要一份案例声明以不进行调整。 从技术上讲,在闰年,如果一年从星期六开始,你可以有 54 周(假设星期天是你一周的第一天。)这是一个极端的情况,但几年前它让我很痛苦.【参考方案2】:看看我的计算。我们的想法是从今年的 1 月 1 日开始算术。
declare @year int=2016, @wk int=31
--A) Single chain calculations
select case datepart(weekday,cast(concat(@year,'-01-01') as date))
when 1 then dateadd(wk,@wk-1,cast(concat(@year,'-01-01') as date))
else dateadd(wk,@wk-1,
dateadd(day, 1/*8 if you want "first full week"*/ - datepart(weekday, cast(concat(@year,'-01-01') as date)),
cast(concat(@year,'-01-01') as date))) end
--B) the same in a better readable form
;with tmp as (
select cast(concat(@year,'-01-01') as date) jan01
)
select case datepart(weekday,jan01)
when 1 then dateadd(wk, @wk-1, jan01)
else dateadd(wk, @wk-1, dateadd(day, 1 - datepart(weekday, jan01), jan01)) end frstDay
from tmp
【讨论】:
'concat' 不是可识别的内置函数名。concat
是在 SQL Server 2012 中引入的。对于早期版本,您可以使用 cast(@year as varchar)+'-01-01'
。 CTE 也于 2008 年首次出现。【参考方案3】:
这是一个使用 DATEDIFF 和 DATEADD 的示例(第 3 行是获取所需值的一行代码)。这可能类似于接受的答案。
我发帖是因为这是我在为自己记录时在函数中使用的分解。
--1. Get the number of Weeks since Monday, January 1, 1900
select DATEDIFF(wk, 0, '01/01/2016') -- 6052 Weeks
--2: Take the value since 1900 + Number of Weeks - 8 Days get you to Sunday.
select DATEADD(wk, 6052 + (31), -8);
--3. Put it all together..
select DATEADD(wk, DATEDIFF(wk, 0, '1/1/2016' ) + (31), -8); --=2016-07-24
【讨论】:
以上是关于给定周数,返回 T-SQL 中一周的第一天的主要内容,如果未能解决你的问题,请参考以下文章