I\'m trying to work out how to calculate actual downtime for various applications from data I\'m storing within a table.
At the moment I\'m just calculating the dif
I had a similar problem, and I got it answered in my question How to Consolidate Blocks of Time?
In your case, this is accomplished with a top 1 self outer apply to get the overlap, and then use either the Overlap's Start time, or if null, the normal Record's end time as the end time.
CREATE TABLE Downtime (
Application VARCHAR(25),
DowntimeStart DATETIME,
DowntimeEnd DATETIME,
Expected INT
)
INSERT Downtime (Application, DowntimeStart, DowntimeEnd, Expected) VALUES -- Act/Exp
('Application Demo', '2014-11-20 17:31:01.467', '2014-11-20 18:01:01.243', 30) -- 30/30
,('Application Demo', '2014-11-28 17:59:00.987', '2014-11-28 18:09:02.167', 26) -- 10/26
,('Application Demo', '2014-11-28 18:00:01.403', '2014-11-28 18:25:01.443', 0) -- 25/0
,('Application Demo', '2014-11-29 19:13:08.580', '2014-11-30 05:30:01.763', 617) -- 617/617
,('Application Demo', '2014-11-30 01:55:01.953', '2014-11-30 03:54:01.730', 0)
SELECT
Records.Application, Records.DowntimeStart, Records.DowntimeEnd, Records.Expected
, DATEDIFF(minute, Records.DowntimeStart, COALESCE(Overlap.DowntimeStart, Records.DowntimeEnd)) AS Actual
-- , Overlap.Application, Overlap.DowntimeStart, Overlap.DowntimeEnd -- For Verification Purposes
FROM Downtime Records
OUTER APPLY (
SELECT TOP 1 Overlap.Application, Overlap.DowntimeStart, Overlap.DowntimeEnd
FROM Downtime Overlap
WHERE Records.Application = Overlap.Application
AND Overlap.DowntimeStart > Records.DowntimeStart
AND Overlap.DowntimeStart BETWEEN Records.DowntimeStart AND Records.DowntimeEnd
ORDER BY Overlap.DowntimeStart
) Overlap
Here's the SQLFiddle with the solution.