Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
999 views
in Technique[技术] by (71.8m points)

tsql - Isoweek in SQL Server 2005

In SQL Server 2008 the isoweek can be found with this:

SELECT datepart(iso_week, getdate())

Before SQL Server 2008 there were no built-in function to find isoweek.

I have been searching high and low for a good syntax to find a userdefined iso_week for SQL Server 2005. I found quite a few solutions. Didn't like any of the solutions I found, most of them didn't work, and they were way too long.

Since the issue is very old, I would expect this issue is depleted and the best solution has been found. I was unable to find a good method though.

I wrote a solution, which I am going to post later. But before I do, I want to make absolutely sure that no one else can match the solution I wrote.

I am hoping to earn the self-learner badge. I urge people to find the best answers out there for this ancient question.

I am going to post my answer after giving people a chance of finding a good solution.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There is a link here for other earlier attempts http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=60510

This is the OLD code for the function

CREATE function f_isoweek(@date datetime)
RETURNS INT
as
BEGIN
DECLARE @rv int

SELECT @rv = datediff(ww, dateadd(ww, datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7,-4),day4)
FROM (SELECT dateadd(ww, datediff(day, 0, @date)/7, 3) day4) a

RETURN @rv
END

After combining @AndriyM 's brilliant answer with my own, we are down to 1 line. This is the NEW code.

CREATE function f_isoweek(@date datetime)
RETURNS INT
as
BEGIN

RETURN (datepart(DY, datediff(d, 0, @date) / 7 * 7 + 3)+6) / 7
-- replaced code for yet another improvement.
--RETURN (datepart(DY, dateadd(ww, datediff(d, 0, @date) / 7, 3))+6) / 7

END

Explanation for the old code (not going to explain the new code. It is fragments from my code and AndriyM's code):

Finding weekday 4 of the chosen date

dateadd(week, datediff(day, 0, @date)/7, 3) 

Finding isoyear - year of weekday 4 of a week is always the same year as the isoyear of that week

datediff(yy, 0, day4)

When adding 3 days to the first day of the isoyear a random day of the first isoweek of the isoyear is found

dateadd(yy, datediff(yy, 0, day4),3)

finding relative week of the first isoweek of the isoyear

datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7

Finding the monday minus 4 days of the first isoweek results in thursday of the week BEFORE the first day of the first isoweek of the isoyear

dateadd(ww, datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7,-4)

Knowing first thursday of the week before the first isoweek and first thursday of the chosen week, makes it is quite easy to calculate the week, it doesn't matter which setting datefirst has since the weekdays of both dates are thursdays.

datediff(ww, dateadd(ww, datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7,-4),day4)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...