Try this from reference Calculate Actual Downtime ignoring overlap in dates/times
DECLARE @clientUsage TABLE (
ID INT PRIMARY KEY NOT NULL IDENTITY(1,1),
ClientName VARCHAR(25),
StartTime DATETIME,
EndTime DATETIME
)
INSERT @clientUsage (ClientName, StartTime, EndTime) VALUES
('client', '2014-11-20 17:31:01.467', '2014-11-20 18:01:01.243')
,('client', '2014-11-28 17:59:00.987', '2014-11-28 18:09:02.167')
,('client', '2014-11-28 18:00:01.403', '2014-11-28 18:25:01.443')
,('client', '2014-11-29 19:13:08.580', '2014-11-30 05:30:01.763')
,('client', '2014-11-30 01:55:01.953', '2014-11-30 03:54:01.730')
,('client 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397')
,('client 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397')
,('client 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397')
,('client 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397')
,('client 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397')
If you use your table instead of temp table
select clientname,sum(actual) from
(SELECT
clienttime.ClientName,
clienttime.StartTime,
clienttime.EndTime,
COALESCE(Actual, 0) AS Actual
FROM @clientUsage clienttime
LEFT OUTER JOIN (
SELECT DISTINCT
D1.ClientName,
MIN(CASE WHEN D1.StartTime < D2.StartTime THEN D1.ID ELSE D2.ID END) AS [ID],
MIN(CASE WHEN D1.StartTime < D2.StartTime THEN D1.StartTime ELSE D2.StartTime END) AS [StartTime],
MAX(CASE WHEN D1.EndTime > D2.EndTime THEN D1.EndTime ELSE D2.EndTime END) AS [EndTime],
DATEDIFF(MINUTE,
MIN(CASE WHEN D1.StartTime < D2.StartTime THEN D1.StartTime ELSE D2.StartTime END),
MAX(CASE WHEN D1.EndTime > D2.EndTime THEN D1.EndTime ELSE D2.EndTime END)) AS Actual
FROM @clientUsage D1
INNER JOIN @clientUsage D2
ON D1.ClientName = D2.ClientName
AND (D1.StartTime BETWEEN D2.StartTime AND D2.EndTime
OR D2.StartTime BETWEEN D1.StartTime AND D1.EndTime)
GROUP BY
D1.ClientName,
D1.StartTime
) Outages
ON Outages.ID = clienttime.ID) op group by clientname
I tested in sql server.