从T-SQL的一周数中获取date

在Microsoft SQL Server中,我有一个星期的编号

(from DATEPART(wk, datecol)) 

但是我想要做的就是把这个回到当天的date范围。

例如,

 SELECT DATEPART(wk, GETDATE()) 

产量10.我想从这个数字推导3/1/2009和3/7/2009。

这可能吗?

Quassnoi的答案是有效的,但如果他们是在一天中的某个date,那么这种方法会让你随时准备清理date(如果你在中间使用一段时间, – 可以使用GETDATE()来testing)。

以前我用过这样的东西:

 SELECT CONVERT(varchar(50), (DATEADD(dd, @@DATEFIRST - DATEPART(dw, DATECOL), DATECOL)), 101), CONVERT(varchar(50), (DATEADD(dd, @@DATEFIRST - DATEPART(dw, DATECOL) - 6, DATECOL)), 101) 

这样做的好处是通过使用@@ DATEFIRST你可以处理非标准的一周开始date(默认是星期天,但是用SET @@ DATEFIRST你可以改变这个)。

这似乎很疯狂,简单的date操作在SQL Server必须是这个神秘的,但你去…

您可以将@WeekNum和@YearNum设置为任何您想要的值 – 在本例中,它们是从@datecolvariables派生的,该variables被设置为GETDATE()以用于说明。 一旦你有这些值,你可以通过使用以下来计算一周的date范围:

 DECLARE @datecol datetime = GETDATE();
 DECLARE @WeekNum INT
       ,@YearNum char(4);

 SELECT @WeekNum = DATEPART(WK,@datecol)
      ,@YearNum = CAST(DATEPART(YY,@datecol)AS CHAR(4));

 - 一旦您设置了@WeekNum和@YearNum,以下计算date范围。
 SELECT DATEADD(wk,DATEDIFF(wk,6,'1/1 /'+ @YearNum)+(@ WeekNum-1),6)AS StartOfWeek;
 SELECT DATEADD(wk,DATEDIFF(wk,5,'1/1 /'+ @YearNum)+(@ WeekNum-1),5)AS EndOfWeek; 
 SELECT DATECOL - DATEPART(weekday, DATECOL), DATECOL - DATEPART(weekday, DATECOL) + 7 

如果一个函数跳到那个星期前一个星期的数字,然后在接下来的几天内逐步进行,直到星期数变化(最多7个步骤),返回新的date?

 CREATE FUNCTION dbo.fnGetDateFromWeekNo (@weekNo int , @yearNo int) RETURNS smalldatetime AS BEGIN DECLARE @tmpDate smalldatetime set @tmpdate= cast(cast (@yearNo as varchar) + '-01-01' as smalldatetime) -- jump forward x-1 weeks to save counting through the whole year set @tmpdate=dateadd(wk,@weekno-1,@tmpdate) -- make sure weekno is not out of range if @WeekNo <= datepart(wk,cast(cast (@yearNo as varchar) + '-12-31' as smalldatetime)) BEGIN WHILE (datepart(wk,@tmpdate)<@WeekNo) BEGIN set @tmpdate=dateadd(dd,1,@tmpdate) END END ELSE BEGIN -- invalid weeknumber given set @tmpdate=null END RETURN @tmpDate END 

如果你的星期从星期一开始(在SQL Server 2008上)

 select datecol, DATEPART(ISOWK, datecol) as week, ((DATEPART(dw, datecol)+5)%7)+1 as weekday, (DATEADD(dd, -((DATEPART(dw, datecol)+5)%7), datecol)) as Monday, (DATEADD(dd, -((DATEPART(dw, datecol)+5)%7)+6, datecol)) as Sunday 
 dateadd( dd, datepart(wk, @Date)*7, convert(smalldatetime, convert(char,year(max(@Date)))+convert(char, '-01-01')) )-1 

在这里,你只需要通过年份和周数。

 DECLARE @Year VARCHAR(4) SET @Year= '2012' DECLARE @FirstDate DATETIME SET @FirstDate = (SELECT DATEADD(dd,1,(SELECT DATEADD(wk,DATEPART(wk,GETDATE())-1,Convert(DAteTime,'01-01-' + @Year)))) ) DECLARE @LastDate DATETIME SET @LastDate =(SELECT DATEADD(dd,4,@FirstDate)) SELECT @FirstDate ,@LastDate 

这应该工作,不pipe@@DATEFIRST

 ALTER FUNCTION dbo.DEV_VW_WeekSerial (@YearNum int, @WeekNum int, @DayNum int) RETURNS Date AS BEGIN DECLARE @FirstDayYear As Date; SET @FirstDayYear='01/01/' + CAST(@YearNum As varchar) RETURN dateadd(d,(@DayNum-datepart(weekday,@FirstDayYear)),dateadd(week, @WeekNum-1,@FirstDayYear)) END 

回答你的问题:

 --CHANGE A WEEK NUMBER BACK INTO A DATE FOR THE FIRST DATE OF THE WEEK DECLARE @TaskWeek INT = 17 DECLARE @TaskYear INT = 2013 SELECT DATEADD(WEEK, @TaskWeek - 1,DATEADD(dd, 1 - DATEPART(dw, '1/1/' + CONVERT(VARCHAR(4),@TaskYear)), '1/1/' + CONVERT(VARCHAR(4),@TaskYear))) 

我已经采取了elindeblom的解决scheme,并对其进行了修改 – 使用string(即使投到date)使我对世界各地使用的不同格式的date感到紧张。 这避免了这个问题。

虽然没有要求,我也包括时间,所以本周结束前1秒午夜:

  DECLARE @WeekNum INT = 12, @YearNum INT = 2014 ; SELECT DATEADD(wk, DATEDIFF(wk, 6, CAST(RTRIM(@YearNum * 10000 + 1 * 100 + 1) AS DATETIME)) + ( @WeekNum - 1 ), 6) AS [start_of_week], DATEADD(second, -1, DATEADD(day, DATEDIFF(day, 0, DATEADD(wk, DATEDIFF(wk, 5, CAST(RTRIM(@YearNum * 10000 + 1 * 100 + 1) AS DATETIME)) + ( @WeekNum + -1 ), 5)) + 1, 0)) AS [end_of_week] ; 

是的,我知道我还在铸造,但从一个数字。 它“感觉”对我更安全。

这导致:

  start_of_week end_of_week ----------------------- ----------------------- 2014-03-16 00:00:00.000 2014-03-22 23:59:59.000 

给它@Year和@Week,返回那一周的第一个date。

 Declare @Year int ,@Week int ,@YearText varchar(4) set @Year = 2009 set @Week = 10 set @YearText = @Year print dateadd(day ,1 - datepart(dw, @YearText + '-01-01') + (@Week-1) * 7 ,@YearText + '-01-01') 

我只是将SELECT和CASE语句结合在一起(对于我的情况,周一标记了一周的第一天,而不想处理SET DATEFIRST命令:

 CASE DATEPART(dw,<YourDateTimeField>) WHEN 1 THEN CONVERT(char(10), DATEADD(DD, -6, <YourDateTimeField>),126) + ' to ' + CONVERT(char(10), <YourDateTimeField>,126) WHEN 2 THEN CONVERT(char(10), <YourDateTimeField>,126) + ' to ' + CONVERT(char(10), DATEADD(DD, 6, <YourDateTimeField>),126) WHEN 3 THEN CONVERT(char(10), DATEADD(DD, -1, <YourDateTimeField>),126) + ' to ' + CONVERT(char(10), DATEADD(DD, 5, <YourDateTimeField>),126) WHEN 4 THEN CONVERT(char(10), DATEADD(DD, -2, <YourDateTimeField>),126) + ' to ' + CONVERT(char(10), DATEADD(DD, 4, <YourDateTimeField>),126) WHEN 5 THEN CONVERT(char(10), DATEADD(DD, -3, <YourDateTimeField>),126) + ' to ' + CONVERT(char(10), DATEADD(DD, 3, <YourDateTimeField>),126) WHEN 6 THEN CONVERT(char(10), DATEADD(DD, -4, <YourDateTimeField>),126) + ' to ' + CONVERT(char(10), DATEADD(DD, 2, <YourDateTimeField>),126) WHEN 7 THEN CONVERT(char(10), DATEADD(DD, -5, <YourDateTimeField>),126) + ' to ' + CONVERT(char(10), DATEADD(DD, 1, <YourDateTimeField>),126) ELSE 'UNK' END AS Week_Range 

除了第一周和最后一周之外,大部分选票的答案都可以正常工作。 当datecol值为“2009-01-01”时 ,结果将为01/03/200912/28/2008

我的解决scheme

 DECLARE @Date date = '2009-03-01', @WeekNum int, @StartDate date; SELECT @WeekNum = DATEPART(WEEK, @Date); SELECT @StartDate = DATEADD(DAY, -(DATEPART(WEEKDAY, DATEADD(YEAR, DATEDIFF(YEAR, 0, @Date), 0)) + 6), DATEADD(YEAR, DATEDIFF(YEAR, 0, @Date), 0)); SELECT CONVERT(nvarchar, CASE WHEN @WeekNum = 1 THEN CAST(DATEADD(YEAR, DATEDIFF(YEAR, 0, @Date), 0) AS date) ELSE DATEADD(DAY, 7 * @WeekNum, @StartDate) END, 101) AS StartOfWeek ,CONVERT(nvarchar, CASE WHEN @WeekNum = DATEPART(WEEK, DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, @Date) + 1, 0))) THEN DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, @Date) + 1, 0)) ELSE DATEADD(DAY, 7 * @WeekNum + 6, @StartDate) END, 101) AS EndOfWeek; 

这将在第一周显示01/01/200901/03/2009 ,并显示第十周的03/01/200903/07/2009

我认为这将是你想要的。 你可以用你想要的expression式replace这些variables。

 SELECT DATEADD(week, @weekNumber - 1, DATEADD(DAY, @@datefirst - DATEPART(weekday, CAST(YEAR(GETDATE()) AS VARCHAR) + '-01-01') - 6, CAST(YEAR(GETDATE()) AS VARCHAR) + '-01-01')) 
 DECLARE @dayval int, @monthval int, @yearval int SET @dayval = 1 SET @monthval = 1 SET @yearval = 2011 DECLARE @dtDateSerial datetime SET @dtDateSerial = DATEADD(day, @dayval-1, DATEADD(month, @monthval-1, DATEADD(year, @yearval-1900, 0) ) ) DECLARE @weekno int SET @weekno = 53 DECLARE @weekstart datetime SET @weekstart = dateadd(day, 7 * (@weekno -1) - datepart (dw, @dtDateSerial), @dtDateSerial) DECLARE @weekend datetime SET @weekend = dateadd(day, 6, @weekstart) SELECT @weekstart, @weekend 

回答:

 select DateAdd(day,-DATEPart(DW,<Date>), <Date>) [FirstDayOfWeek] ,DateAdd(day,-DATEPart(DW,<Date>)+6, <Date>) [LastDayOfWeek] FROM <TABLE> 

这适用于我:

 select convert(varchar(50), dateadd(dd, - datepart(dw, DATECOL) + 1, DATECOL), 101), convert(varchar(50), dateadd(dd, - datepart(dw, DATECOL) + 7, DATECOL), 101) 

我没有花时间来testing这里的每一个答案,但没有看起来像这样简单和有效:

 DECLARE @WeekNum int DECLARE @YearNum char(4) SELECT DATEADD(wk, DATEDIFF(wk, 6, '1/1/' + @YearNum) + (@WeekNum-1), 6) AS StartOfWeek SELECT DATEADD(wk, DATEDIFF(wk, 5, '1/1/' + @YearNum) + (@WeekNum-1), 5) AS EndOfWeek