从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/2009和12/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/2009和01/03/2009 ,并显示第十周的03/01/2009和03/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