On top of my head, I think one of Joe Selcoโs books had this as an example of a problem. You can find the excerpt available on Google.
It could be closer. I think you really did not do the subquery in the right way.
UPDATE table SET dtOut = ( SELECT MIN(t2.dtIn) FROM [table] as t2 WHERE t2.id <> table.id AND t2.type = table.type AND table.dtIn < t2.dtIn AND t2.dtIn < table.dtOut AND table.dtOut <= t2.dtOut ) WHERE EXISTS ( SELECT 1 FROM [table] as t3 WHERE t3.type = table.type AND t3.id <> table.id AND table.dtIn < t3.dtIn AND t3.dtIn < table.dtOut AND table.dtOut <= t3.dtOut )
EDIT I missed the id column at the top of the page, so itโs obvious that itโs better to check than to make sure that the endpoints do not match. The solution is probably simpler if you can assume that two lines of the same type have dtIn.
Btw, there is no reason to use CROSS APPLY when the subquery will do exactly the same job.
EDIT 2 I did a little testing, and I think my request is processing the script in your diagram. There is one case where he may not do what you want.
For this type, think of the last two segments S1 and S2 in order of start time. S2 begins after S1, but also imagine that it ends before S1. S2 is completely contained in the interval S1, so it is either insignificant or the information for two segments must be divided into the third segment and that the problem becomes more complicated.
So, this decision simply assumes that they can be ignored.
EDIT 3 based on update merge comment
SQLFiddle sent by OP
-- eliminate redundant rows DELETE dT1 WHERE EXISTS ( SELECT * FROM tbl dT2 WHERE dT1.Type = dT2.Type AND dT1.dtIn = dT2.dtIn AND ( dT1.dtOut < dT2.dtOut OR (dT1.dtOut = dT2.dtOut AND dT1.id < dT2.id) ) ); --adjust dtOuts to the max dates UPDATE tbl SET dtOut = COALESCE(( SELECT MAX(dtOut) FROM tbl as t1 WHERE t1.type = tbl.type ), dtOut); -- Do the actual updates of dtOut UPDATE tbl SET dtOut = COALESCE(( SELECT MIN(dtIn) FROM tbl as t2 WHERE t2.type = tbl.type AND t2.id <> tbl.id AND t2.dtIn >= tbl.dtIn AND t2.dtIn < tbl.dtOut ), dtOut);
Or one of the two updates below should replace the two updates above.
UPDATE tbl SET dtOut = ( SELECT COALESCE( MIN(dtIn), (SELECT MAX(dtOut) FROM tbl as tmax WHERE tmax.type = tbl.type) ) FROM tbl as tmin WHERE tmin.type = tbl.type AND tmin.dtIn > tbl.dtIn ); UPDATE tbl SET dtOut = COALESCE( ( SELECT MIN(dtIn) FROM tbl as tmin WHERE tmin.type = tbl.type AND tmin.dtIn > tbl.dtIn ), ( SELECT MAX(dtOut) FROM tbl as tmax WHERE tmax.type = tbl.type ) );