I am trying to craft a SQL statement to pull sample values from a DB. The table contains values that pertain to tool changes in a CNC machine. The current statement I have p
This is called the "islands problem" and I've seen this as a solution (credit Itzik Ben Gan)
select tool_number,
min(time) 'in',
max(time) 'out',
count(*)
from (
select tool_number,
time,
ROW_NUMBER() OVER (ORDER BY time) - ROW_NUMBER() OVER (PARTITION BY Tool_Number ORDER BY time) AS Grp
from #temp
) as a
group by grp, tool_number
order by min(time)
Here's another approach using LAG/LEAD
:
DECLARE @rawdata TABLE(Tool_Number INT, [Time] TIME(0));
INSERT @rawdata VALUES
(100,'12:00'), (100,'12:01'), (100,'12:02'), (100,'12:03'),
(200,'12:04'), (200,'12:05'),
(100,'12:06'), (100,'12:07');
;WITH x AS
(
SELECT Tool_Number, [Time],
s = CASE Tool_number WHEN LAG(Tool_number,1) OVER (ORDER BY [Time])
THEN 0 ELSE 1 END,
e = CASE Tool_number WHEN LEAD(Tool_number,1) OVER (ORDER BY [Time])
THEN 0 ELSE 1 END
FROM @rawdata
),
y AS
(
SELECT Tool_Number, s, [Time], e = LEAD([Time],1) OVER (ORDER BY [Time])
FROM x WHERE 1 IN (s,e)
)
SELECT Tool_number, TIME_IN = [Time], TIME_OUT = e
FROM y
WHERE s = 1
ORDER BY TIME_IN;
Results:
Tool_number TIME_IN TIME_OUT
----------- -------- --------
100 12:00:00 12:03:00
200 12:04:00 12:05:00
100 12:06:00 12:07:00