We first need to do a self join to get all the rows in the table with the Same FKID:
SELECT *
FROM T AS t1
INNER JOIN T AS t2
ON t2.FKID = t1.FKID -- SAME FKID
AND t2.ID <> t1.ID -- Different ID;
The condition t2.ID <> t1.ID will ensure you aren't joining the same row to itself, instead looking for other rows in the same table. This will return all combinations of rows, e.g.
If however you only want each tuple once, you can change to t2 > t1.ID which will return only
Then for overlapping ranges, the verbose version of the logic is:
- Start date of 2nd Row is after Start of first row and before and end date of 1st Row OR
- End date of 2nd Row is after Start of 1st Row and before the end date of 1st Row
So in SQL terms this becomes:
CREATE TABLE #T (ID INT, FKID INT, Start DATETIME, [End] DATETIME, TotalTime INT);
INSERT INTO #T(ID, FKID, Start, [End], TotalTime)
VALUES
(208, 40, '2021-07-29 09:30:00', '2021-07-29 09:30:00', 0.9),
(209, 37, '2021-07-29 10:00:00', '2021-07-29 10:00:00', 0.9),
(210, 39, '2021-07-29 10:15:00', '2021-07-29 11:32:00', 77.76),
(211, 40, '2021-07-29 13:00:00', '2021-07-29 14:17:00', 77.76),
(212, 34, '2021-07-29 13:00:00', '2021-07-29 14:28:00', 88.8685714285714),
(213, 39, '2021-07-29 10:30:00', '2021-07-29 11:47:00', 77.76);
SELECT t1.*
FROM #T AS t1
INNER JOIN #T AS t2
ON t2.FKID = t1.FKID -- SAME FKID
AND t2.ID <> t1.ID -- Different ID
WHERE (t2.Start > t1.Start AND t2.Start < t1.[End])
OR (t2.[End] > t1.Start AND t2.[End] < t1.[End]);
We can however simplify this with De Morgan's laws to simply:
SELECT t1.*
FROM #T AS t1
INNER JOIN #T AS t2
ON t2.FKID = t1.FKID -- SAME FKID
AND t2.ID <> t1.ID -- Different ID
WHERE t2.Start < t1.[End]
AND t2.[End] > t1.Start;
In both cases the output is:
| ID |
FKID |
Start |
End |
TotalTime |
| 210 |
39 |
2021-07-29 10:15:00.000 |
2021-07-29 11:32:00.000 |
77.76 |
| 213 |
39 |
2021-07-29 10:30:00.000 |
2021-07-29 11:47:00.000 |
77.76 |
Example on db<>fiddle
If you want to include rows where the start date equals the end date of a previous row, then just change < to <= and > to >=:
SELECT t1.*
FROM #T AS t1
INNER JOIN #T AS t2
ON t2.FKID = t1.FKID -- SAME FKID
AND t2.ID <> t1.ID -- Different ID
WHERE t2.Start <= t1.[End]
AND t2.[End] >= t1.Start;
Example on db<>fiddle note rows with ID 214 and 215