I'm using SQL Server 2008R2 in this problem. Here's an example dataset:
WIRE_ID FROM TO CLASS
05485 0.000 1.520 PL
05485 1.520 3.050 PL
05485 3.050 22.250 SL
05485 3.050 22.250 SP
05485 22.250 33.530 SL
05485 22.250 33.530 QT
05485 33.530 43.580 QT
05485 43.580 52.580 PL
05485 52.580 57.910 QT
114161 0.000 3.000 SW
114161 3.000 5.000 SL
114161 5.000 6.000 SL
114161 6.000 9.412 YN
114161 9.412 10.549 YN
114161 10.549 12.375 CM
114161 12.375 14.438 SL
114161 14.438 15.126 SL
So, a non-sequential ID associated ranged values and a group/classification. As you can see you can sometimes have duplicate intervals as different classes may be applied. Ultimately the result I'd like to achieve would look like the following:
WIRE_ID FROM TO CLASS
05485 0.000 3.050 PL
05485 3.050 22.250 SL
05485 3.050 22.250 SP
05485 22.250 33.530 SL
05485 22.250 43.580 QT
05485 43.580 52.580 PL
05485 52.580 57.910 QT
114161 0.000 3.000 SW
114161 3.000 6.000 SL
114161 6.000 10.549 YN
114161 10.549 12.375 CM
114161 12.375 15.126 SL
Seems easy at first and I've constructed a solution that works, but once I apply it to the entire data-set it grinds to a halt. Ideally I need a solution that can handle a million rows of this style of data in a more or less efficient manner... Here's my solution:
Declare @WIRE_CLASS Table(WIRE_ID varchar(25), [FROM] float, [TO] float, CLASS varchar(15));
Insert @WIRE_CLASS(WIRE_ID, [FROM], [TO], CLASS) Values
('05485',0.000,1.520,'PL'),
('05485',1.520,3.050,'PL'),
('05485',3.050,22.250,'SL'),
('05485',3.050,22.250,'SP'),
('05485',22.250,33.530,'SL'),
('05485',22.250,33.530,'QT'),
('05485',33.530,43.580,'QT'),
('05485',43.580,52.580,'PL'),
('05485',52.580,57.910,'QT'),
('114161',0.000,3.000,'SW'),
('114161',3.000,5.000,'SL'),
('114161',5.000,6.000,'SL'),
('114161',6.000,9.412,'YN'),
('114161',9.412,10.549,'YN'),
('114161',10.549,12.375,'CM'),
('114161',12.375,14.438,'SL'),
('114161',14.438,15.126,'SL');
;with WIRE AS (
SELECT
WIRE_ID,
FROM,
TO,
CLASS
FROM
WIRE_CLASS
), ISLANDS AS (
SELECT
ROW_NUMBER() OVER (ORDER BY WI.WIRE_ID, WI.FROM) ID,
WI.WIRE_ID,
WI.FROM,
WI.TO,
WI.CLASS,
CASE WHEN WI2.WIRE_ID IS NULL THEN 1 ELSE 0 END BREAKER
FROM
WIRE WI
LEFT JOIN WIRE WI2 ON
WI2.WIRE_ID = WI.WIRE_ID
AND (WI2.TO = WI.FROM)
AND WI2.CLASS = WI.CLASS
), DATA AS(
SELECT
IS1.WIRE_ID, IS1.FROM, IS1.TO, IS1.CLASS,
(SELECT sum(BREAKER) FROM ISLANDS IS2 WHERE IS1.ID >= IS2.ID) BREAKER
FROM ISLANDS IS1
)
SELECT
DA.WIRE_ID,
MIN(DA.FROM),
MAX(DA.TO),
MIN(DA.CLASS)
FROM DATA DA
GROUP BY
DA.WIRE_ID,
BREAKER,
DA.CLASS
ORDER BY
DA.WIRE_ID,
MIN(DA.[FROM]),
MAX(DA.[TO])
Can you suggest a better way to do this??? Thanks a bunch SQL gurus!