SQL Server not showing correct week numbers for given date
SQL Server is showing week 53 for first week of 2011 except 1th of January, and needs to be week 1.
Below is the query and output:
declare @T table (dt datetime)
insert into @T values
('2010-12-26'),
('2010-12-27'),
('2010-12-28'),
('2010-12-29'),
('2010-12-30'),
('2010-12-31'),
('2011-01-01'),
('2011-01-02'),
('2011-01-03'),
('2011-01-04'),
('2011-01-05'),
('2011-01-06'),
('2011-01-07'),
('2011-01-08')
select dt,DATEPART(wk,dt) from @T
Output:
2010-12-26 00:00:00.000 53
2010-12-27 00:00:00.000 53
2010-12-28 00:00:00.000 53
2010-12-29 00:00:00.000 53
2010-12-30 00:00:00.000 53
2010-12-31 00:00:00.000 53
2011-01-01 00:00:00.000 1
2011-01-02 00:00:00.000 2
2011-01-03 00:00:00.000 2
2011-01-04 00:00:00.000 2
2011-01-05 00:00:00.000 2
2011-01-06 00:00:00.000 2
2011-01-07 00:00:00.000 2
2011-01-08 00:00:00.000 2
I want SQL Server to show week 1 from Dec 26th - 开发者_Python百科Jan 1th. Does anybody know how to accomplish this?
Thanks and regards, Aschwin.
It was alot harder than I first expected. I am comparing the end of last year to see if it is qualified to be part of the new year. If so i set the week as 1, otherwise i just use the normal week.
declare @T table (dt datetime)
insert into @T values
('2010-12-25'),
('2010-12-26'),
('2010-12-27'),
('2010-12-28'),
('2010-12-29'),
('2010-12-30'),
('2010-12-31'),
('2011-01-01'),
('2011-01-02'),
('2011-01-03'),
('2011-01-04'),
('2011-01-05'),
('2011-01-06'),
('2011-01-07'),
('2011-01-08'),
('2011-12-31'),
('2012-01-01')
select dt,
week = case when dt + 6 - datediff(day, -1, dt) % 7 = dateadd(year, datediff(year,-1, dt), 0)
then 1 else datepart(week, dt) end from @t
Proof:
https://data.stackexchange.com/stackoverflow/q/110527/
I am not sure it holds for all years (but it looks like it) but you could solve this using a CASE statement.
SELECT dt
, CASE WHEN DATEPART(wk, dt) <> 53
THEN DATEPART(wk, dt)
ELSE 1
END
FROM @T
The new ISO_WEEK datepart doesn't apply to your requested output.
I Created 2 functions to deal with this issue 1) to get First or last day of the week 2) to get the week number or year
function 1
CREATE FUNCTION [dbo].[fn_GetDayOf]
(
@Date datetime,
--@FirstDayOfWeek int = 7,
@Mode int =1
)
/*
Mode 1: First Day Of Week
Mode 2: Last Day Of Week
*/
RETURNS datetime
WITH EXECUTE AS CALLER
BEGIN
Declare @Return datetime
--SET DATEFIRST @FirstDayOfWeek
IF @Mode = 1
BEGIN
select @Return = dateadd(day,-(datepart(weekday,@date)-1),convert(date,@date))
END
ELSE IF @Mode = 2
BEGIN
select @Return = dateadd(SECOND,-1,convert(datetime,dateadd(day,(datepart(weekday,@date)),convert(date,@date))))
END
ELSE
BEGIN
SET @Return = @Date
END
--SET DATEFIRST 7
RETURN @Return
END
Function 2
CREATE FUNCTION [dbo].[fn_GetYearWeek]
(
@Date datetime,
--@FirstDayOfWeek int = 7,
@Mode int =1
)
/*
Mode 1 = Week Number
Mode 2 = Year
*/
RETURNS INT
BEGIN
declare @Return int
IF @Mode = 1
BEGIN
select @Return = case when datepart(week,[dbo].[fn_GetDayOf] (@Date,1)) <> datepart(week,[dbo].[fn_GetDayOf] (@Date,2)) then datepart(week,[dbo].[fn_GetDayOf] (@Date,1)) else datepart(week,[dbo].[fn_GetDayOf] (@Date,2)) end
END
ELSE IF @Mode = 2
BEGIN
select @Return = case when datepart(WEEK,[dbo].[fn_GetDayOf] (@Date,1)) <> datepart(week,[dbo].[fn_GetDayOf] (@Date,2)) then datepart(YEAR,[dbo].[fn_GetDayOf] (@Date,1)) else datepart(YEAR,[dbo].[fn_GetDayOf] (@Date,2)) end
END
ELSE
BEGIN
SET @Return = -1
END
Return @Return
END
Running Example
declare @T table (dt datetime)
insert into @T values
('2010-12-25'),
('2010-12-26'),
('2010-12-27'),
('2010-12-28'),
('2010-12-29'),
('2010-12-30'),
('2010-12-31'),
('2011-01-01'),
('2011-01-02'),
('2011-01-03'),
('2011-01-04'),
('2011-01-05'),
('2011-01-06'),
('2011-01-07'),
('2011-01-08'),
('2011-12-31'),
('2012-01-01'),
('2012-01-02'),
('2012-12-31'),
('2013-01-01')
select
dt,
datepart(week,dt),
--case when datepart(week,[dbo].[fn_GetDayOf] (dt,1)) <> datepart(week,[dbo].[fn_GetDayOf] (dt,2)) then datepart(week,[dbo].[fn_GetDayOf] (dt,1)) else datepart(week,[dbo].[fn_GetDayOf] (dt,2)) end
[dbo].[fn_GetYearWeek] (dt,1),
[dbo].[fn_GetYearWeek] (dt,2)
from @T
result:
Another way to retrieve the total number of weeks in current year:
DECLARE @LASTDAY DATETIME
DECLARE @weeks INT
SET @LASTDAY = DATEADD(ms,-3,DATEADD(yy,0,DATEADD(yy,DATEDIFF(yy,0,GETDATE())+1,0)))
SELECT @weeks = CASE DATEname(dw,@LASTDAY)
WHEN 'MONDAY' THEN DATEPART(WK, DATEADD(wk,DATEDIFF(wk,7,@LASTDAY),5))
WHEN 'TUESDAY' THEN DATEPART(WK, DATEADD(wk,DATEDIFF(wk,7,@LASTDAY),5))
WHEN 'WEDNESDAY' THEN DATEPART(WK, DATEADD(wk,DATEDIFF(wk,7,@LASTDAY),5))
ELSE DATEPART(WK, @LASTDAY)
END
select @weeks
精彩评论