Reputation: 313
I seem to be asking a lot of SQL questions at the moment. (I would normally write a program to sort the data into a report table, however at the moment that is not possible, and needs to be done using SQL)
The Question I need a where clause that returns results with the next working day. i.e. Monday 01/01/01 the next working day would be Tuesday 02/01/01 which could be achieved with a simple date add. However on a Friday 05/01/01 the next working day is Monday 08/01/01. Is there anything built in to help cope with this easily?
Thanks for your advice.
Upvotes: 1
Views: 7094
Reputation: 1
It's been basically answered above, but it took me a while to get it and I thought maybe this will help somebody. Is used a simple CASE-WHEN.
This is a check in order to find out which days are weekdays
DATEPART(dw, date) -> MON through FRI = 1,2,3,4,5 SAT = 6, SUN = 7
This is the CASE-WHEN:
CASE
WHEN DATEPART(weekday, date) <= 5 THEN date -- weekdays, no change
WHEN DATEPART(weekday, date) = 6 THEN date + 2 -- SAT + 2 = MON
WHEN DATEPART(weekday, date) = 6 THEN date + 1 -- SUN + 1 = MON
END AS 'WEEKDAY_DATES'
Check, if the statement actually gets you weekdays only:
CASE
WHEN DATEPART(weekday, date) <= 5 THEN DATENAME(weekday, date)
WHEN DATEPART(weekday, date) = 6 THEN DATENAME(weekday, date + 2)
WHEN DATEPART(weekday, date) = 6 THEN DATENAME(weekday, date + 1)
END AS 'WEEKDAY_NAMES'
Upvotes: 0
Reputation: 1718
Here's what I did for a one-off application:
WHILE EXISTS (SELECT * FROM Holidays WHERE CONVERT(VARCHAR, HolidayDate,101) = CONVERT(VARCHAR,@DateVariable 101 ) OR DATENAME(WEEKDAY, @DateVariable)='SATURDAY' OR DATENAME(WEEKDAY, @DateVariable)='SUNDAY')
BEGIN
SET @DateVariable = DateAdd(day,1,@DateVariable)
PRINT @DateVariable -- If you want
END
Note that, our Holidays
table stores all holidays for the past and future years.
Upvotes: 1
Reputation: 2062
All Credit to Cashif -- I modified his to include a Holiday table (tblHolidays
with a date field HolDate
) which is very lightweight -- about 10 rows a year if you're lucky enough to get that many days off!
My version returns date
type (which I find easier to work with). I also run thru this more than once -- if Thursday is your startday and Friday is a holiday, you have to again add 2 more days to get to Monday (or the next working day). Then it checkes to make sure the next week doesn't start with a holiday.
CREATE FUNCTION [dbo].[GetNextWorkingDay] (@givenDate DATE)
RETURNS DATE
AS
BEGIN
DECLARE @workingDate DATETIME
IF (DATENAME(dw , @givenDate) = 'Friday')
BEGIN
SET @workingDate = DATEADD(day, 3, @givenDate)
END
ELSE IF (DATENAME(dw , @givenDate) = 'Saturday')
BEGIN
SET @workingDate = DATEADD(day, 2, @givenDate)
END
ELSE
BEGIN
SET @workingDate = DATEADD(day, 1, @givenDate)
END
while ((Select count(*) from tblHolidays where holdate = @workingDate) > 0)
begin
set @workingDate = dateadd(dd,1,@WorkingDate)
end
-- if adding a day makes it a Saturday, add 2 more to get to Monday (and test to make sure the week doesn't start with a holiday)
IF (DATENAME(dw , @workingDate) = 'Saturday')
BEGIN
SET @workingDate = DATEADD(day, 2, @workingDate)
END
while ((Select count(*) from tblHolidays where holdate = @workingDate) > 0)
begin
set @workingDate = dateadd(dd,1,@WorkingDate)
end
RETURN @workingDate
END
... of course you should refactor so the code doesn't repeat, and include a while clause to repeat only as many times as needed to get to a working day, but I have a deadline... that'll be for another less hectic day.
Upvotes: 1
Reputation: 18624
How about somethin like this?
select * from table
where (date = dateadd(dd,1,@today) and datepart(weekday,@today) not in (6,0) ) --its not friday or saturday
or (date = dateadd(dd,2,@today) and datepart(weekday,@today) = 0) -- its saturday
or (date = dateadd(dd,3,@today) and datepart(weekday,@today) = 6) --its friday
the date attribute should have the same time as @today or else you have to also use between
Upvotes: 0
Reputation: 1850
What you need is a calendar table. Getting the next working days is not so simple if you need to account for holidays other than the weekend. The table basically contains just two columns Date and an integer field indicating whether it is a working/non working day- but there can be other columns for - example quarter etc as well.
This table is populated once a year and then maintained as necessary. Getting the result for next working day then becomes as simple as a query like this.
SELECT field1,filed2 from your table T where your date_Field = (SELECT min(date) From calendar table where WorkingDay = 1 and date > GetDate())
/P
Upvotes: 0
Reputation: 14430
CREATE FUNCTION dbo.uf_GetNextWorkingDay (@givenDate DATETIME)
RETURNS DATETIME
AS
BEGIN
DECLARE @workingDate DATETIME
IF (DATENAME(dw , @givenDate) = 'Friday')
BEGIN
SET @workingDate = DATEADD(day, 3, @givenDate)
END
ELSE IF (DATENAME(dw , @givenDate) = 'Saturday')
BEGIN
SET @workingDate = DATEADD(day, 2, @givenDate)
END
ELSE
BEGIN
SET @workingDate = DATEADD(day, 1, @givenDate)
END
RETURN @workingDate
END
A good article http://ryanfarley.com/blog/archive/2005/02/14/1685.aspx
Upvotes: 3
Reputation: 1001
You could do this with a simple case statement.
select case when datepart(dw, getdate()) >= 6 then getdate() + (9 - datepart(dw, getdate())) else getdate() + 1 end
Upvotes: 0
Reputation: 102478
You could do this with a simple day check and add 3 days rather than one if its a Friday. However, do you need to take into consideration public holidays though?
Upvotes: 2
Reputation: 340211
The key is to use the DATEPART(weekday,@date) function, it'll return the day of the week, so if it's saturday or sunday you just add one or two to the current date to get the desired result.
You can create a user defined function to do so easily, for example Pinal Dave has this
CREATE FUNCTION dbo.udf_GetPrevNextWorkDay (@dtDate DATETIME, @strPrevNext VARCHAR(10))
RETURNS DATETIME
AS
BEGIN
DECLARE @intDay INT
DECLARE @rtResult DATETIME
SET @intDay = DATEPART(weekday,@dtDate)
--To find Previous working day
IF @strPrevNext = 'Previous'
IF @intDay = 1
SET @rtResult = DATEADD(d,-2,@dtDate)
ELSE
IF @intDay = 2
SET @rtResult = DATEADD(d,-3,@dtDate)
ELSE
SET @rtResult = DATEADD(d,-1,@dtDate)
--To find Next working day
ELSE
IF @strPrevNext = 'Next'
IF @intDay = 6
SET @rtResult = DATEADD(d,3,@dtDate)
ELSE
IF @intDay = 7
SET @rtResult = DATEADD(d,2,@dtDate)
ELSE
SET @rtResult = DATEADD(d,1,@dtDate)
--Default case returns date passed to function
ELSE
SET @rtResult = @dtDate
RETURN @rtResult
END
GO
Upvotes: 4