Microsoft SQL Server 2008
--
Questions
--
Followers
Top Experts
Zero AI Policy
We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.
additionally: please provide:
field names
field data types (or we will assume things like datetime)
sample data
elapsed time for multiple datetime combinations. I tried using DATEADD(SS,(DATEDIFF(SS,@d
Ex.
Task Table
task_ID Completion_Date
1 '2013-03-10 8:30:18.007'
2 '2013-03-15 10:00:18.007'
3 '2013-03-16 8:30:18.007'
4 '2013-03-18 8:30:18.007'
......
Execute a sql function to calculate elapsed time for all sections
getElapsedTime('2013-03-10
getElapsedTime('2013-03-16
Results
Elapsed time for task 1 to task 2
Days : hours : Minutes
Elapsed time for task 3 to task 4
Days : hours : Minutes
employeeId, taskId, Commence_date, Completion_Date
tracking over rows through one field is possible but overly complicates your objective.
what is indicated above is that rows 1 & 2 belong to each other, and rows 3 & 4 belong to each other - by "sequential order" - that's not what I would recommend.
Is it possible to change the structure of this temp table?






EARN REWARDS FOR ASKING, ANSWERING, AND MORE.
Earn free swag for participating on the platform.
CREATE FUNCTION dbo.NetWorkDays (
 @StartDate DATETIME
 , @EndDate DATETIME
 )
RETURNS INT
AS
BEGIN
 DECLARE @result INT
  , @StartDate2 DATETIME
  , @EndDate2 DATETIME
  , @DateSwap1 DATETIME
  , @DateSwap2 DATETIME
  , @ReturnNegative BIT
 SET @DateSwap1 = @StartDate
 SET @Dateswap2 = @EndDate
 SET @ReturnNegative = 0
 IF @EndDate < @StartDate
 BEGIN
  SET @ReturnNegative = 1
  SET @StartDate = @Dateswap2
  SET @EndDate = @DateSwap1
 END
 SET @StartDate2 = dateadd(d, 8 - datepart(dw, @StartDate), @StartDate)
 SET @EndDate2 = dateadd(d, 1 - datepart(dw, @EndDate), @EndDate)
 SET @result = datediff(d, @StartDate2, @EndDate2) * 5 / 7 + datediff(d, @StartDate, @StartDate2) - 1 + datediff(d, @EndDate2, @EndDate) - CASE 
   WHEN datepart(dw, @StartDate) = 1
    THEN 1
   ELSE 0
   END - CASE 
   WHEN datepart(dw, @EndDate) = 7
    THEN 1
   ELSE 0
   END
 IF @ReturnNegative = 1
 BEGIN
  SET @result = @result * - 1
 END
 RETURN @result
END;
and there's scope for an improved method of weekend detection (using modulus) that could be incorporated.
I'm open to any table structure. I just need to be able to calculate the elapsed time for two datetime values. The results of the query will be in a Crystal Report. I can arrange the results in the correct order on the report.

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.
e.g.
a start at 13:00:00 is evaluated to 17:00:00 = 14400 seconds (4 hours)
a finish at 12:00:00 is evaluated from 08:00:00 = 14400 seconds (4 hours)
e.g:
start day1 13:00:00 = 14400 seconds (4 hours)
finish day2 12:00:00 = 14400 seconds (4 hours)
= 28800 seconds (8 hours)
start dayMon 13:00:00 = 14400 seconds (4 hours) on that Monday
finish dayTue 12:00:00 = 14400 seconds (4 hours) on that Tuesday
= 28800 seconds (8 hours)
+ 5 * 28800 seconds (5 * 8 hours) [Tue/Wed/Thu/Fri/Mon]
= 172800 seconds (48 hours)
HOWEVER.....
08:00:00 to 17:00:00 is actually 9 hours....
SO
a maximum of 28800 seconds (8 hours) per day is imposed, which is OK except that a start of 09:00:00 and finish of 17:00:00 on the same day is also 28800 seconds (8 hours) and no further deduction is made. Basically you MIGHT get an extra hour on the start day and/or an extra hour on the finish day because this 1 hour (probably lunch) isn't taken into account.
You should definitely take the time to look over the test results at this sqlfiddle link. There you will find some few deliberate test cases and some randomly generated data used to evaluate this new function's output. It is also compared to the former networkdays function (which is also compared to calculations done by Excel when generating the random data).
I have opted to return seconds from this new function which can be further calculated to days/hours as needed, like this:
, dbo.NetWorkSecs(start,fini
If you don't want seconds returned then the function itself can be modified to return decimal hours - this I leave to you.
Please do evaluate the function at sqlfiddle. Here's the current code
CREATE FUNCTION dbo.NetWorkSecs (
       @p_StartDate as DATETIME
     , @p_EndDate as DATETIME
     )
RETURNS INT
AS
BEGIN
 DECLARE
    @result       as INT  = 0
  , @v_StartDate  as DATE
  , @v_EndDate    as DATE
  , @v_StartDate2 as DATE
  , @v_EndDate2   as DATE
  , @v_StartTime  as TIME
  , @v_EndTime    as TIME
  , @v_ShiftStart as TIME = cast('08:00:00' as time)
  , @v_ShiftEnd   as TIME = cast('17:00:00' as time)
  , @v_ShiftSecs  as INT  = (8*60*60)
  , @v_OnStart    as INT
  , @v_OnEnd      as INT
IF @p_StartDate <> @p_EndDate /* i.e. no point doing more if they are equal */
  BEGIN
    IF @p_EndDate < @p_StartDate
         /* finish before start, so flip over the given dates for "sequence of event" consistency */
         BEGIN
          SET @v_StartTime = cast(@p_EndDate as TIME)
          SET @v_EndTime   = cast(@p_StartDate as TIME)
          SET @v_StartDate = dateadd(day,1,cast(@p_EndDate as date))   /* next day, because start time accounted for seperately */
          SET @v_EndDate   = dateadd(day,0,cast(@p_StartDate as date)) /* start of last day because finish time accounted for seperately */
         END
    ELSE
         BEGIN
          SET @v_StartTime = cast(@p_StartDate as TIME)
          SET @v_EndTime   = cast(@p_EndDate as TIME)
          SET @v_StartDate = dateadd(day,1,cast(@p_StartDate as date)) /* next day, because start time accounted for seperately */
          SET @v_EndDate   = dateadd(day,0,cast(@p_EndDate as date))   /* start of last day because finish time accounted for seperately */
         END
         
        IF @v_StartDate = @v_EndDate /* i.e. after taking time into accout there are no whole days between start and finish times */
          BEGIN
             SET @v_OnStart = datediff(second,@v_StartTime ,@v_ShiftEnd)       /* seconds on start date within shift */
             SET @v_OnEnd   = datediff(second,@v_ShiftStart,@v_EndTime)        /* seconds on end date within shift */
             SET @result =   CASE
                                when @v_OnStart > @v_ShiftSecs then @v_ShiftSecs when @v_OnStart > 0 then @v_OnStart else 0
                             END
                           + CASE
                                when @v_OnEnd > @v_ShiftSecs then @v_ShiftSecs when @v_OnEnd > 0 then @v_OnEnd else 0
                             END
             END
        ELSE
          BEGIN
             SET @v_OnStart = datediff(second,@v_StartTime ,@v_ShiftEnd)       /* seconds on start date within shift */
             SET @v_OnEnd   = datediff(second,@v_ShiftStart,@v_EndTime)        /* seconds on end date within shift */
             /* the following logic from source 'networkdays' function, results are consistent with Excel networkdays */
             SET @v_StartDate2 = dateadd(d, 8 - datepart(dw, @v_StartDate), @v_StartDate)
             SET @v_EndDate2 = dateadd(d, 1 - datepart(dw, @v_EndDate), @v_EndDate)
             SET @result = (
                            (  datediff(d, @v_StartDate2, @v_EndDate2) * 5 / 7 
                             + datediff(d, @v_StartDate, @v_StartDate2) - 1 
                             + datediff(d, @v_EndDate2, @v_EndDate) 
                             - CASE 
                                   WHEN datepart(dw, @v_StartDate) = 1
                                    THEN 1
                                   ELSE 0
                                   END 
                             - CASE 
                                   WHEN datepart(dw, @v_EndDate) = 7
                                    THEN 1
                                   ELSE 0
                                   END)
                           * @v_ShiftSecs)
                           /* above we multiply by shift seconds for each intervening work day, and below, add seconds of first and last days) */
                           + CASE
                                when @v_OnStart > @v_ShiftSecs then @v_ShiftSecs when @v_OnStart > 0 then @v_OnStart else 0
                             END
                           + CASE
                                when @v_OnEnd > @v_ShiftSecs then @v_ShiftSecs when @v_OnEnd > 0 then @v_OnEnd else 0
                             END
           END
   END
 RETURN @result
END
;
Also, there is no accommodation for holidays (at all), just Sat/Sun. (& Here I have NOT attempted revise the previous logic of NetWorkDays (which I didn't write)). Ideally this weekend logic would be independent of dbms settings and even better would be the ability to nominate which days of the week are excluded - but neither has been attempted.
This new function can be easily tweaked for different day shifts such as 09:00 to 18:00 simply by changing the variable values. BUT it's worth mentioning that this function isn't suited to shifts that span a date (e.g. a 'night shift' starting 21:00 and finishing 06:00 the next day), this would require additional logic.
[edit, aded excel file for reference, data is random!]
http://www.sqlservercentral.com/Forums/Topic14491-23-1.aspx#bm1362656
by: davidcriley (citing Patrick Jasinski as originator)






EARN REWARDS FOR ASKING, ANSWERING, AND MORE.
Earn free swag for participating on the platform.
Thanks
the algorithm from seconds to higher units is pretty simple
minutes = seconds/60
hours = seconds/60/60
days = seconds/60/60/24
a scalar function can only return one value, plus you will want to avoid calling the function multiple times. so 'nest' your query, e.g.
select
start
, finish
, networksecs/60 as networkminutes
,etc.
from (
select
start
, finish
, dbo.NetWorkSecs(start,fini
from tasks
) as derived
The function could probably be revised to return a "time" type...
then you could use:
, datepart(day,networktime) as days
, datepart(hour,networktime)
, datepart(minute,networktim
there's a bucket load of voluntary work for these points
it will be much simpler to return a numeric, it could be minutes instead of seconds
nb: you can aggregate a numeric so calculating totals in much easier this way.
does it absolutely have to be displayed as days/hours/minutes?
why not just decimals hours? (seconds/3600)
e.g 101.55 hours

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.
select
  start
, finish
, (networksecs/28800) as days
, ((networksecs - ((networksecs/28800)*28800))/3600) as hours
, ((networksecs - (((networksecs/28800)*28800) + ((networksecs - ((networksecs/28800)*28800))/3600)*3600)) /60) as minutes
from (
           select
             start
           , finish
           , dbo.NetWorkSecs(start,finish) as networksecs
          from tasks
        ) as derived
;
see it at:http://sqlfiddle.com/#!3/42277/3 (look for the second set of results)
all of this would be marginally simpler if the function returned minutes
To display 3 values from the function would require either:
a. calling the function 3 times, or
b. nesting so the single returned value can be reused
b. is better for performance
so, it will not matter if the function returns minutes, seconds or datetime you would still need to interpret the result for display into 3 seperate parts.






EARN REWARDS FOR ASKING, ANSWERING, AND MORE.
Earn free swag for participating on the platform.
Select @ReturnValue = CONVERT(VARCHAR(3),(networ
+ CONVERT(VARCHAR(3),((netwo
...... 'Minutes'
Would something like that work?
I did consider it but would not recommend it
you are free to try it of course, in theory yes it can be done - just not sure its wise

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 you relented on display by days/hours/minutes, and simply presented decimal hours that would be simpler....
otherwise I don't understand the question
I am not a development shop.... the function COULD return varchar in days/hours/minutes and I have shown you how that is possible also
what next?
For example. If I calculate the elapsed time from 2012-06-28 10:37:14.997 to 2012-07-11 08:31:02.813, I receive 12Days 21Hours 53Minutes. However, If I use the code above(excluding weekends, including 8-5 work hours), I receive 284040 for the totalSeconds. When I convert the total seconds to day, hours, minutes, I receive 3 days, 78 hours, and 4734 minutes. The days are way off even with weekends excluded. Is there a way to get the amount of days, hours, and minutes from the total seconds and have it display like 12Days 21Hours 53Minutes?
select @totalSeconds/60 as minutes -4734
select @totalseconds/60/60 as hours -78
select @totalSeconds/60/60/24 as days --3
The correct calculations are these:
declare @networksecs as int = 284040
select
  (@networksecs/28800) as days
, ((@networksecs - ((@networksecs/28800)*28800))/3600) as hours
, ((@networksecs - (((@networksecs/28800)*28800) + ((@networksecs - ((@networksecs/28800)*28800))/3600)*3600)) /60) as minutes
DAYS HOURS MINUTES
9    6     54






EARN REWARDS FOR ASKING, ANSWERING, AND MORE.
Earn free swag for participating on the platform.
Cheers.
Paul

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.
Both for start and end date.
declare @dateFrom as datetime
declare @dateUntil as datetime
set @dateFrom = {ts '2016-09-08 10:00:00'}
set @dateUntil = {ts '2016-09-08 17:10:00'}
select cast(dbo.GetWorkingStr(@da
results in 7.166666 (should be 7.000000)
set @dateFrom = {ts '2016-09-08 10:00:00'}
set @dateUntil = {ts '2016-09-08 18:10:00'}
select cast(dbo.GetWorkingStr(@da
results in 7.000000 (is correct)
Microsoft SQL Server 2008
--
Questions
--
Followers
Top Experts
Microsoft SQL Server 2008 is a suite of relational database management system (RDBMS) products providing multi-user database access functionality.Component services include integration (SSIS), reporting (SSRS), analysis (SSAS), data quality, master data, T-SQL and performance tuning. Major improvements include the Always On technologies and support for unstructured data types.