I just can\'t seem to get this query figured out. I need to combine rows of time-consecutive states into a single state.
This question is similar to the question fou
Here's another approach:
SELECT
name,
min(start_inst) AS start_inst,
max(end_inst) AS end_inst,
code,
subcode
FROM
(
SELECT
A.*,
COUNT
(
CASE WHEN start_inst = previous_end_inst THEN NULL
ELSE 1
END
)
OVER
(
ORDER BY
start_inst,
name,
code,
subcode
) AS group_number
FROM
(
SELECT
name,
start_inst,
end_inst,
LAG
(
end_inst
)
OVER
(
PARTITION BY
name,
code,
subcode
ORDER BY
start_inst
) AS previous_end_inst,
code,
subcode
FROM
data
) A
) B
GROUP BY
name,
code,
subcode,
group_number
ORDER BY
group_number
Basically:
For each row, subquery A finds the previous end time for the given name, code, and subcode.
For each row, subquery B calculates the "group number" -- a running count of preceeding rows (in order of start_inst, name, code, and subcode) where the previous end time calculated in Step 1 is not equal to the start time.
The outer query aggregates by group number.
For better or worse, this approach, unlike @stevo's, will create a new "group" if there's a "gap" between the end time of one record and the start time of the next. For example, if you were to create a gap between 12:57 and 13:00 like this...
UPDATE data
SET start_inst = TO_DATE('9/12/2011 13:00', 'MM/DD/YYYY HH24:MI')
WHERE start_inst = TO_DATE('9/12/2011 12:57', 'MM/DD/YYYY HH24:MI');
...the query above would return two rows like this...
NAME START_INST END_INST CODE SUBCODE
-------------------- ---------------- ---------------- ---------- ----------
.
.
.
Person1 09/12/2011 12:26 09/12/2011 12:57 161 71
Person1 09/12/2011 13:00 09/12/2011 13:07 161 71
.
.
.
...whereas @stevo's query would return one row like this...
NAME START_INST END_INST CODE SUBCODE
-------------------- ---------------- ---------------- ---------- ----------
.
.
.
Person1 12/09/2011 12:26 12/09/2011 13:07 161 71
.
.
.
Hope this helps.