Microsoft SQL Server
--
Questions
--
Followers
Top Experts
I have a sql query to calculate the time between when an order is received to when it is responded to in minutes with the query below. How can I exclude weekends from the total if applicable?
 SELECT
 DateReceived
, TimeReceived
, (DateReceived + cast(cast(TimeReceived as time) as datetime)) AS [Combined Date and Time Received]
, DateClosed
, TimeClosed
, (DateClosed + cast(cast(TimeClosed as time) as datetime)) Â Â AS [Combined Date and Time Closed]
, datediff(minute, (DateReceived + cast(cast(TimeReceived as time) as datetime)), (DateClosed + cast(cast(TimeClosed as time) as datetime)))
 AS [Minutes from Receipt to Closure]
FROM tableX
WHERE
DateReceived >= @from
 AND DateReceived < @until
Zero AI Policy
We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.
http://www.sqlservercentral.com/Forums/Topic412112-150-1.aspx#bm412179
Can you incorporate that with my existing query? I am a novice at SQL. Not sure how I would incorporate the link to my query.
UPDATE: when I reference the link I meant the formula suggested on that site not actually incorporating the link into the formula (just wanted to clarify after re-reading my comment) not that novice!
Thank you,
SELECT
  DateReceived
, TimeReceived
, (DateReceived + cast(cast(TimeReceived as time) as datetime)) AS [Combined Date and Time Received]
, DateClosed 
, TimeClosed
, (DateClosed + cast(cast(TimeClosed as time) as datetime))     AS [Combined Date and Time Closed]
, datediff(minute, (DateReceived + cast(cast(TimeReceived as time) as datetime))
-(CASE WHEN DATENAME(dw, DateReceived) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, DateReceived) = 'Saturday' THEN 1 ELSE 0 END), 
(DateClosed + cast(cast(TimeClosed as time) as datetime))) 
  AS [Minutes from Receipt to Closure]
FROM tableX
WHERE 
DateReceived >= @from
  AND DateReceived <  @until






EARN REWARDS FOR ASKING, ANSWERING, AND MORE.
Earn free swag for participating on the platform.
there is a scalar function here that will calcuate the net working days (networkdays), Â and also a more thorough one here that will calculate working time in minutes (i.e. exclude holidays and only include the standard working day.
The second one was modified to return a varchar in  a "day hour minute pattern" or it provides minutes as a varchar, but can be easily modified back to int.
In your calculation of [Minutes from Receipt to Closure] do you want a 24 hour day, or an 8 hour day? (plus exclude weekends)
Both of these are scalar functions, so once you create them they are used in your query like this:
,dbo.fcn_MadeForThis( (DateReceived + cast(cast(TimeReceived as time) as datetime)), (DateClosed + cast(cast(TimeClosed as time) as datetime)))
 AS [Minutes from Receipt to Closure]
In other words, it would simply replace the existing datediff() which is also a scalar function.
So, 8 hour day or 24 hour day, what is your preference? Â (plus exclude weekends)
@ Barry62 - Your query yielded the same result as the original query. The date received is almost never on a weekend (though it does happen occasionally) but rather a weekend may go by before we respond. For example:
I receive an order request on Friday at 4:15PM I don't respond to the service request until Monday at 8:30 AM. On original; calculation I get over 2 days as the response time but it should be 45 minutes (Office hours 8:30AM-5PM, - Saturday, - Sunday). But I do want to account for those occasions that a request does come in over the weekend and calculate accordingly.
PortletPaul - How would I incorporate that into the original query does that get appended to the end? I get an error if I appended to the end.
8 hour day or 24 hour day?

Get a FREE t-shirt when you ask your first question.
We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.
I have revised it a bit to correct some errors(I think):
SELECT
  DateReceived
, TimeReceived
, (DateReceived + cast(cast(TimeReceived as time) as datetime)) AS [Combined Date and Time Received]
, DateClosed 
, TimeClosed
, (DateClosed + cast(cast(TimeClosed as time) as datetime))     AS [Combined Date and Time Closed]
, datediff(minute, (DateReceived + cast(cast(TimeReceived as time) as datetime))
,(DateClosed + cast(cast(TimeClosed as time) as datetime)))
-(CASE WHEN DATENAME(dw, DateReceived) = 'Sunday' THEN 1440 ELSE 0 END)
-(CASE WHEN DATENAME(dw, DateClosed) = 'Saturday' THEN 1440 ELSE 0 END) 
+(CASE WHEN DATENAME(dw, DateReceived) = 'Sunday' THEN datediff(minute, (DateReceived + cast(cast('17:00' as time) as datetime))) ELSE 0 END)
+(CASE WHEN DATENAME(dw, DateRecieved) = 'Saturday' THEN datediff(minute, (DateReceived + cast(cast('17:00' as time) as datetime))) ELSE 0 END)
  AS [Minutes from Receipt to Closure]
FROM tableX
WHERE 
DateReceived >= @from
  AND DateReceived <  @until
As for your provided query  - It yielded the following Error (what change should I make):
@PortletPaul
Forgive me Paul, but as you know I am a novice at SQL, when you state that I have to create the function first what do you mean? Will that modify the database in anyway? I would prefer the 8 Hours calculation. Our Business hours are 8:30AM-5PM M-F. I am not concerned with holidays for the calculation.
Thank you both for your patience with me on this.
yes, it will add one function
>>Â will it blow-up my database and the city I live in?
no
All you do is get the code, like a query, and execute it (and assuming you have the rights to create functions it'll work)
you can practice as sqlfiddle
just go to http://sqlfiddle.com
in a drop down pick sql server 2008 (or 2102)
copy that function code block, and paste into the left hand panel at sqlfiddle, then click 'build schema'
it isn't scary
if you do not have the rights to create this function, find someone who can..






EARN REWARDS FOR ASKING, ANSWERING, AND MORE.
Earn free swag for participating on the platform.
those business hours include a 'lunch' period, which the function simply ignores.
for times prior to 9:00am it assumes them to be 9:00am, and by doing it this way it effectively ignores that lunch break, now this might have some unfortunate impacts because in many cases the whole elapsed time isn't too long in your data. We can probably tweak the function further to make it work 8:30 17:00 but that is 8.5 hours not 8. Try it as is first please but look for test cases where the start time is in the range 08:30 - 09:00
>>I am not concerned with holidays for the calculation.
good, I took out that piece.
The function's author had allowed for this but you need a table of holiday dates
SELECT
  DateReceived
, TimeReceived
, (DateReceived + cast(cast(TimeReceived as time) as datetime)) AS [Combined Date and Time Received]
, DateClosed 
, TimeClosed
, (DateClosed + cast(cast(TimeClosed as time) as datetime))     AS [Combined Date and Time Closed]
, datediff(minute, (DateReceived + cast(cast(TimeReceived as time) as datetime))
,(DateClosed + cast(cast(TimeClosed as time) as datetime)))
-(CASE WHEN DATENAME(dw, DateReceived) = 'Sunday' THEN 1440 ELSE 0 END)
-(CASE WHEN DATENAME(dw, DateClosed) = 'Saturday' THEN 1440 ELSE 0 END) 
+(CASE WHEN DATENAME(dw, DateReceived) = 'Sunday' THEN datediff(minute, (DateReceived + cast(cast(TimeReceived as time) as datetime)),(DateReceived + cast(cast('17:00' as time) as datetime))) ELSE 0 END)
+(CASE WHEN DATENAME(dw, DateReceived) = 'Saturday' THEN datediff(minute, (DateReceived + cast(cast(TimeReceived as time) as datetime)),(DateReceived + cast(cast('17:00' as time) as datetime))) ELSE 0 END)
  AS [Minutes from Receipt to Closure]
FROM tableX
WHERE 
DateReceived >= @from
  AND DateReceived <  @until
@evengeekier, if you pursue this method, you also have to adjust the original datediff's returned number (line 8) this isn't in working minutes so there is more maths to be performed.
SELECT
   DateReceived
 , TimeReceived
 , (DateReceived + cast(cast(TimeReceived AS TIME) AS DATETIME)) AS [Combined Date and Time Received]
 , DateClosed
 , TimeClosed
 , (DateClosed + cast(cast(TimeClosed AS TIME) AS DATETIME)) AS [Combined Date and Time Closed]
 , datediff(minute, (DateReceived + cast(cast(TimeReceived AS TIME) AS DATETIME)), (DateClosed + cast(cast(TimeClosed AS TIME) AS DATETIME)))
     - (  CASE WHEN DATENAME(dw, DateReceived) = 'Sunday' THEN 1440 ELSE 0 END  ) 
     - (  CASE WHEN DATENAME(dw, DateClosed) = 'Saturday' THEN 1440 ELSE 0 END  ) 
     + (  CASE WHEN DATENAME(dw, DateReceived) = 'Sunday' THEN 
               datediff(minute, (DateReceived + cast(cast(TimeReceived AS TIME) AS DATETIME)), (DateReceived + cast(cast('17:00' AS TIME) AS DATETIME)))
          ELSE 0 END  ) 
     + (  CASE WHEN DATENAME(dw, DateReceived) = 'Saturday' THEN 
               datediff(minute, (DateReceived + cast(cast(TimeReceived AS TIME) AS DATETIME)), (DateReceived + cast(cast('17:00' AS TIME) AS DATETIME)))
          ELSE 0 END  ) 
    AS [Minutes from Receipt to Closure]
FROM tableX
WHERE DateReceived >= @from AND DateReceived < @until

Get a FREE t-shirt when you ask your first question.
We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.
If I wanted to now compare a different set of dates (i.e DateReceived, TimeReceived to DateOpened, TimeOpened) would I need to create a new function? or just change the query?
(I would test it but had to step away from my workstation)
Thank you.
@Barry62 - Your query returned the same result as with the weekends etc. Thank you for your help in either case.
do you need a different dateadd() function for each query?
NO, absolutely not. The whole point is you put some piece of logic into a function to re-use it.
you simply put different date fields into the function - just like dateadd() or datediff() - these are also functions.
you can use it in any query where you need this logic (as long as you can access the function of course)
@evengeekier - I tried. :) Â I think I will defer to PortletPaul for this solution. Â I will be saving it for future reference, though.






EARN REWARDS FOR ASKING, ANSWERING, AND MORE.
Earn free swag for participating on the platform.
thank you.
Date Received = 3/11/2013 Time Received =7:00AM
Date Closed = 3/19/2013 Time Closed = 8:53PM
dbo.NetWorkMins = 3360
Should be 3570 right? (8.5 hours * 7 days (excludes weekends)

Get a FREE t-shirt when you ask your first question.
We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.
Date Closed = 3/19/2013 Time Closed = 8:53PM -> treated as 17:00 that day
elapsed 9 days, work days = 7, *8*60 = 3360
the real question is, do you consider the "work day" to be 8 hours or 8.5 hours.
Most of the time the .5 would be due to a lunch break and is excluded from calculation of work time...
If I make it 8.5 it will affect every full day too, not just those the exceptions that occur between 08:30-09:00; so a Time Received 12:00 day 1 and 12:00 day 2 = 8.5*60
savvy?
Is this really what you want? are you doubly sure it isn't an 8 hour day?
  Declare @StartHour decimal(2,1)  = 8.5     /* Start of business hours (as an argument) */
then also change line 1 to start with:
ALTER FUNCTION
then re-run, it will update the function and now work with an 8.5 hour working day






EARN REWARDS FOR ASKING, ANSWERING, AND MORE.
Earn free swag for participating on the platform.
I have one further idea of this topic I will experiment with...
if a start time is >= 8:30 and <Â 9:00 I will add 30 minute to both start time and finsh time
this will 'push' those start time into scope
I think this will work - stay tuned
You will need to change line 1 to read
Alter Function
Create Function NetWorkMins(
  @StartDate DateTime
, @EndDate DateTime
) 
Returns INT
AS
/*
origin:
http://stackoverflow.com/questions/5274208/calculate-business-hours-between-two-dates
Arjun Khosla
Sep 5 '12 at 7:57
Modified, PortetPaul Experts-Exchange.com for question
http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/Q_28077021.html#a39021904
aa. name change to NetWorkMins
a. removal of holiday table, code commented out
b. all comments use slash*, and some other cosmetics
USAGE
, dbo.NetWorkMins(Start,Finish) as [Working Minutes]
*/
Begin
    Declare @WorkMin int    = 0              /* Initialize counter */
    Declare @Reverse bit                     /* Flag to hold if direction is reverse */
    Declare @OpenAtHour time  = '08:30:00'   /* Actual Start of business hours  */
    Declare @StartHour int  = 9              /* Start of business hours  */
    Declare @EndHour int    = 17             /* End of business hours (as an argument) */
    /* Declare @Holidays Table (HDate DateTime) */   /*   Table variable to hold holidayes */
    /* If dates are in reverse order, switch them and set flag */
    If @StartDate>@EndDate 
    Begin
        Declare @TempDate DateTime = @StartDate
        Set @StartDate = @EndDate
        Set @EndDate = @TempDate
        Set @Reverse = 1
    End
    Else Set @Reverse = 0
    /* Get country holidays from table based on the country code (Feel free to remove this or modify as per your DB schema) */
    /* Insert Into @Holidays (HDate) Select HDate from HOLIDAY Where COUNTRYCODE = @Country and HDATE>= DateAdd(dd, DateDiff(dd,0,@StartDate), 0) */
    /* "push" timings 30 minutes if between real opening time and the 8 hour day timeframe */
    /* this is for a specific purpose and is not generic, store opens at 08:30 so to not truncate, push these conditions into consideration */
    If cast(@StartDate as time) >= @OpenAtHour AND DatePart(HH, @StartDate) < @StartHour
    Begin
       Set @StartDate = DateAdd(minute, 30 , @StartDate)
       Set @EndDate   = DateAdd(minute, 30 , @EndDate)
    End
    If DatePart(HH, @StartDate)<@StartHour  Set @StartDate = DateAdd(hour, @StartHour,    DateDiff(DAY, 0, @StartDate)) /* If Start time is less than start hour, set it to start hour */
    If DatePart(HH, @StartDate)>= @EndHour+1 Set @StartDate = DateAdd(hour, @StartHour+24, DateDiff(DAY, 0, @StartDate)) /* If Start time is after end hour, set it to start hour of next day */
    If DatePart(HH, @EndDate)>= @EndHour+1   Set @EndDate   = DateAdd(hour, @EndHour,      DateDiff(DAY, 0, @EndDate))   /* If End time is after end hour, set it to end hour */
    If DatePart(HH, @EndDate)<@StartHour    Set @EndDate   = DateAdd(hour, @EndHour-24,   DateDiff(DAY, 0, @EndDate))   /* If End time is before start hour, set it to end hour of previous day*/
    If @StartDate>@EndDate Return 0
    /* If Start and End is on same day */
    If DateDiff(Day,@StartDate,@EndDate) <=  0
    Begin
        If Datepart(dw,@StartDate) > 1 And DATEPART(dw,@StartDate) < 7  /*  If day is between sunday and saturday */
            /* If (Select Count(*) From @Holidays Where HDATE = DateAdd(dd, DateDiff(dd,0,@StartDate), 0)) = 0 */ /*  If day is not a holiday */
                If @EndDate<@StartDate Return 0 Else Set @WorkMin = DATEDIFF(MI, @StartDate, @EndDate) /*  Calculate difference */
            /* Else Return 0 */
        Else Return 0
    End
    Else Begin
        Declare @Partial int = 1   /*  Set partial day flag */
        While DateDiff(Day,@StartDate,@EndDate) > 0   /*  While start and end days are different */
        Begin
            If Datepart(dw,@StartDate)>1 And DATEPART(dw,@StartDate)<7    /*   If this is a weekday */
            Begin
                If 1 = 1 /* due to removal of holiday (see next line), leave 1 = 1 in lieu */ 
                         /* (Select Count(*) From @Holidays Where HDATE = DateAdd(dd, DateDiff(dd,0,@StartDate), 0)) = 0 */ /*  If this is not a holiday */
                Begin
                    If @Partial = 1  /*  If this is the first iteration, calculate partial time */
                    Begin 
                        Set @WorkMin = @WorkMin + DATEDIFF(MI, @StartDate, DateAdd(hour, @EndHour, DateDiff(DAY, 0, @StartDate)))
                        Set @StartDate = DateAdd(hour, @StartHour+24, DateDiff(DAY, 0, @StartDate)) 
                        Set @Partial = 0 
                    End
                    Else Begin      /*  If this is a full day, add full minutes */
                        Set @WorkMin = @WorkMin + (@EndHour-@StartHour)*60        
                        Set @StartDate = DATEADD(DD,1,@StartDate)
                    End
                End
                Else Set @StartDate = DATEADD(DD,1,@StartDate)  
            End
            Else Set @StartDate = DATEADD(DD,1,@StartDate)
        End
        If Datepart(dw,@StartDate) > 1 And DATEPART(dw,@StartDate) < 7  /*  If last day is a weekday */
            /* If (Select Count(*) From @Holidays Where HDATE = DateAdd(dd, DateDiff(dd,0,@StartDate), 0)) = 0 */  /*  And it is not a holiday */
            If @Partial = 0 Set @WorkMin = @WorkMin + DATEDIFF(MI, @StartDate, @EndDate) Else Set @WorkMin = @WorkMin + DATEDIFF(MI, DateAdd(hour, @StartHour, DateDiff(DAY, 0, @StartDate)), @EndDate)
    End 
   
    If @Reverse = 1 Set @WorkMin = -@WorkMin /* minus of value */
    Return @WorkMin
End
;

Get a FREE t-shirt when you ask your first question.
We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.
Order Received on:
02/14/2013 @ 8:33AM
Closed On:
03/08/2013 @ 11:05AM
Function returns = 7832
Paul I am very grateful. Thank you again.
don't forget that when it comes time to put this into 'production' you must have that function defined in that database :)
Cheers, Paul
Microsoft SQL Server
--
Questions
--
Followers
Top Experts
Microsoft SQL Server is a suite of relational database management system (RDBMS) products providing multi-user database access functionality.SQL Server is available in multiple versions, typically identified by release year, and versions are subdivided into editions to distinguish between product functionality. Component services include integration (SSIS), reporting (SSRS), analysis (SSAS), data quality, master data, T-SQL and performance tuning.