I have a MySQL 5.6 table defined thusly:
DROP TABLE IF EXISTS `ranges`;
CREATE TABLE `ranges` (
`id` int(6) unsigned NOT NULL,
`start` datetime NOT NULL,
`end` datetime NOT NULL);
INSERT INTO `ranges` (`id`, `start`, `end`) VALUES
(1, '2017-12-16 00:00:00', '2017-12-16 04:00:00'),
(1, '2017-12-16 12:00:00', '2017-12-16 16:00:00'),
(1, '2017-12-16 03:00:00', '2017-12-16 13:00:00'),
(2, '2017-12-16 00:00:00', '2017-12-16 05:00:00'),
(2, '2017-12-16 07:00:00', '2017-12-16 14:00:00'),
(3, '2017-12-16 00:00:00', '2017-12-16 04:00:00');
I want to merge overlapping time ranges by id and preserve non-overlapping ranges as-is. So id 1 would be collapsed into a single row, whereas ids 2 and 3 would remain as they are since id 2's rows don't overlap and id 3 obviously can't since it has only one row. The resulting output should be:
1, 2017-12-16 00:00:00, 2017-12-16 16:00:00
2, 2017-12-16 00:00:00, 2017-12-16 05:00:00
2, 2017-12-16 07:00:00, 2017-12-16 14:00:00
3, 2017-12-16 00:00:00, 2017-12-16 04:00:00
I've looked at related questions and fiddled with the solution here: https://www.sqlservercentral.com/Forums/Topic826031-8-1.aspx. I attempted to adapt that solution, which isn't dependent on an id column, with this attempt:
SELECT s1.id, s1.Start,
MIN(t1.End) AS End
FROM ranges s1
INNER JOIN ranges t1 ON s1.id = t1.id AND s1.Start <= t1.End
AND NOT EXISTS(SELECT * FROM ranges t2
WHERE t1.id = t2.id AND t1.End >= t2.Start AND t1.End < t2.End)
WHERE NOT EXISTS(SELECT * FROM ranges s2
WHERE s1.id = s2.id AND s1.Start > s2.Start AND s1.Start <= s2.End)
GROUP BY s1.id
ORDER BY s1.id;
However, simply adding the id to all the predicates doesn't give the correct result; it seems to ignore the non-overlapping ranges. Since I don't understand how the original query actually works, I'm rather out to sea as far as the correct incantation. Thank you!
SQLFiddle: http://sqlfiddle.com/#!9/6bf76b/1/0