(PostgreSQL 8.4) I got a great introduction to SQL gaps-and-islands here on Stack Overflow but I still have a question. Many island detection CTEs are based on a running order of a timestamp and some flag which breaks the sequence when it changes. But what if the "break" condition is a little more complex?
CREATE TABLE T1
(
id SERIAL PRIMARY KEY,
val INT, -- some device
status INT -- 0=OFF, 1=ON
);
INSERT INTO T1 (val, status) VALUES (10, 1);
INSERT INTO T1 (val, status) VALUES (10, 0);
INSERT INTO T1 (val, status) VALUES (11, 1);
INSERT INTO T1 (val, status) VALUES (11, 1);
INSERT INTO T1 (val, status) VALUES (10, 0);
INSERT INTO T1 (val, status) VALUES (12, 1);
INSERT INTO T1 (val, status) VALUES (13, 1);
INSERT INTO T1 (val, status) VALUES (13, 0);
INSERT INTO T1 (val, status) VALUES (13, 1);
In this case, val
represents a device, and status
is either ON
or OFF
. I want to select records 1
, 3
, 6
, 7
and 9
with the following logic.
- #10 turns ON -- OK, new sequence, include in SELECT
- #10 turns OFF -- ends sequence properly, ignore row
- #11 turns ON -- OK, new sequence, include in SELECT
- #11 turns ON -- duplicate, ignore row
- #10 turns OFF -- #10 wasn't ON, ignore
- #12 turns ON -- OK, implicitly turns OFF #11, include in SELECT
- #13 turns ON -- OK, implicitly turns OFF #12, include in SELECT
- #13 turns OFF -- ends sequence properly, ignore row
- #13 turns ON -- OK, new sequence, include in SELECT
Basically, only one device can be ON at a time, and the "break" condition is that:
- new.val = running.val AND new.status = 0
- new.val <> running.val AND new.status = 1
I'm looking for something in the form of a CTE, no cursors please.
OFF
rows at all. – Sapient