Reputation: 87
I have a database table with a Begindate (datetime) and Enddate (datetime). This table contains activity durations. Now I am trying to create a function to calculate the total duration based on non-overlapping activities within a specified begindate-enddate.
An exaple would be as follow:
I am calling upon this function giving the parameters: Begindate='2012-08-16 10:00' Enddate='2012-08-16 18:00'
Now let's say the following data is in the table:
Now I would love the following to happen:
The total returned will be: 6 hours and 30 minutes.
If anyone could help me with this I would be very grateful! :)
Upvotes: 1
Views: 404
Reputation: 19356
It might be easier to calculate missing ranges and then substract durations from complete period:
declare @begindate datetime = '20120816 10:00:00'
declare @enddate datetime = '20120816 18:00:00'
; with supplement as (
select begindate, enddate
from daterangetable
-- overlapping ranges only
where begindate <= @enddate
and enddate >= @begindate
union all
-- empty start range to catch missing start intervals
select @begindate, @begindate
union all
-- empty end range to catch missing end intervals
select @enddate, @enddate
)
select datediff (minute, @begindate, @enddate)
- sum (datediff (minute, gapStart, gapEnd)) Minutes
from
(
select max(d2.enddate) gapStart,
d1.begindate gapEnd
from supplement d1
cross join supplement d2
-- d2 range must start before d1 range
where d2.begindate < d1.begindate
group by d1.begindate
-- Range is completely covered if d2 ends after d1 begins
-- so it should be removed
having max(d2.enddate) < d1.begindate
) missingRanges
Two ranges overlap if end of first one is after start of second one and start of first one is before end of second one. See the link for (much better) explanation.
If you are not using Sql Server 2005 or newer, you will need to move code inside with
into derived tables for supplement d1 and supplement d2.
And here is Sql Fiddle with example.
Upvotes: 3