December 31, 2008 at 7:13 pm
andrewd.smith (12/23/2008)
Here's a method of calculating the Nth working day in the future without using a CTE or tally table.
DECLARE @days int
SELECT @days = 10
DECLARE @inputDate datetime
SELECT @inputDate = '2008-12-23'
DECLARE @weekDay int
SELECT @weekDay = DATEDIFF(day, 0, @inputDate) % 7
/* @weekDay = 0 (Monday), 2 (Tuesday), ... , 5 (Saturday), 6 (Sunday) */
DECLARE @dayOffset int
SELECT @dayOffset = CASE @weekDay
WHEN 6 THEN @days + (@days / 5) * 2 /* Sunday */
WHEN 5 THEN 1 + @days + (@days / 5) * 2 /* Saturday */
ELSE @days + ((@days + @weekDay) / 5) * 2 END
SELECT DATEADD(day, @dayOffset, @inputDate)
The method only works if [font="Courier New"]@days > 0[/font].
If [font="Courier New"]@inputDate[/font] is guaranteed to be a working day (neither Saturday nor Sunday), then the expression simplifies to:
DECLARE @days int
SELECT @days = 10
DECLARE @inputDate datetime
SELECT @inputDate = '2008-12-23'
SELECT DATEADD(day, @days + ((@days + DATEDIFF(day, 0, @inputDate) % 7 ) / 5) * 2, @inputDate)
Whoops... sorry... there's a fly in that ointment...
DECLARE @days int
SELECT @days = 5
DECLARE @inputDate datetime
SELECT @inputDate = '2002-01-05 00:00:00' --Saturday
DECLARE @weekDay int
SELECT @weekDay = DATEDIFF(day, 0, @inputDate) % 7
/* @weekDay = 0 (Monday), 2 (Tuesday), ... , 5 (Saturday), 6 (Sunday) */
DECLARE @dayOffset int
SELECT @dayOffset = CASE @weekDay
WHEN 6 THEN @days + (@days / 5) * 2 /* Sunday */
WHEN 5 THEN 1 + @days + (@days / 5) * 2 /* Saturday */
ELSE @days + ((@days + @weekDay) / 5) * 2 END
SELECT DATEADD(day, @dayOffset, @inputDate) [font="Arial Black"]--Returns 2002-01-13 00:00:00.000... a Sunday[/font]
--Jeff Moden
Change is inevitable... Change for the better is not.
December 31, 2008 at 7:55 pm
Fellow who goes by the handle "Fraggle" posted a function at the following URL... it seems to work quite reliably for the days ahead that I tested it for...
http://www.sqlservercentral.com/Forums/Topic153606-203-3.aspx#BM591629
--Jeff Moden
Change is inevitable... Change for the better is not.
January 2, 2009 at 4:40 am
Apologies for my stupid mistake in the expression for Saturdays and Sundays.
The following is a corrected version. Note that [font="Courier New"]@days/5[/font] is replaced by [font="Courier New"](@days-1)/5[/font] in the expression for Saturdays and Sundays.
DECLARE @days int
SELECT @days = 5
DECLARE @inputDate datetime
SELECT @inputDate = '2002-01-05'
DECLARE @weekDay int
SELECT @weekDay = DATEDIFF(day, 0, @inputDate) % 7
/* @weekDay = 0 (Monday), 2 (Tuesday), ... , 5 (Saturday), 6 (Sunday) */
DECLARE @dayOffset int
SELECT @dayOffset = CASE @weekDay
WHEN 6 THEN @days + ((@days - 1) / 5) * 2 /* Sunday */
WHEN 5 THEN 1 + @days + ((@days - 1) / 5) * 2 /* Saturday */
ELSE @days + ((@days + @weekDay) / 5) * 2 END
SELECT DATEADD(day, @dayOffset, @inputDate)
The above returns the date 2002-01-11 (Friday) rather than 2002-01-13 (Sunday).
January 4, 2009 at 3:27 pm
Here's my take. )
declare @numberBusinessDaysToAdd int
declare @basedate datetime
set @numberBusinessDaysToAdd = 14
set @basedate = '20090101 17:30'
-- first move base date on to the start of the next day
set @basedate = dateadd(d, datediff(d, '19700101', @basedate) + 1, '19700101')
-- move base date on to the first working day (if not already)
DECLARE @0BasedDayOfWeek int
SET @0BasedDayOfWeek = datediff(d, '19700105', @basedate) % 7 -- get differential from a known Monday
IF @0BasedDayOfWeek > 4 -- if we're saturday or Sunday
SET @basedate = dateadd(d, 7 - @0BasedDayOfWeek, @basedate) -- then add the appropriate number of days to make it to the next monday
-- now add weeks / days as appropriate
set @basedate = dateadd(d, @numberBusinessDaysToAdd % 5, dateadd(ww, @numberBusinessDaysToAdd / 5, @basedate))
Edit -> changed a couple of variable names
Atlantis Interactive - SQL Server Tools
My blog[/url]
Why I wrote a sql query analyzer clone
Viewing 4 posts - 16 through 18 (of 18 total)
You must be logged in to reply to this topic. Login to reply