(PostgreSQL 8.4) Продолжая мой предыдущий пример, я хочу углубить свое понимание обработки промежутков и островов с помощью оконных функций. Рассмотрим следующую таблицу и данные:
CREATE TABLE T1
(
id SERIAL PRIMARY KEY,
val INT, -- some device
status INT -- 0=OFF, 1=ON
);
INSERT INTO T1 (val, status) VALUES (10, 0);
INSERT INTO T1 (val, status) VALUES (11, 0);
INSERT INTO T1 (val, status) VALUES (11, 1);
INSERT INTO T1 (val, status) VALUES (10, 1);
INSERT INTO T1 (val, status) VALUES (11, 0);
INSERT INTO T1 (val, status) VALUES (10, 0);
Как объяснялось ранее, устройства включаются и выключаются, и на этот раз я хочу извлечь определенную последовательность:
- показать все новые записи состояния
ON
, которые не дублируются (одно и то же устройство дважды подряд) - показать соответствующий
OFF
статус текущегоON
устройства
Самое близкое, что я мог получить, это:
SELECT * FROM (
SELECT *
,lag(val, 1, 0) OVER (PARTITION BY status ORDER BY id) last_val
,lag(status, 1, -1) OVER (PARTITION BY val ORDER BY id) last_status
FROM t1
) x
WHERE (last_val <> val OR last_status <> status)
AND (status = 1 OR last_status <> -1)
ORDER BY id
Это отфильтровывает больше фиктивных данных, которые не включены в образец, но, по сути, речь идет об удалении последующих дубликатов (независимо от статуса) и первых OFF
записей, которые не совпадают. Записи 3
, 4
, 5
и 6
возвращаются, но мне не нужна пятая, это OFF
, которая пришла после новой ON
. Поэтому мне нужно перепрыгнуть через этот пробел и найти следующий правильный OFF
для текущего активного устройства.
- 10 выключается - в этом контексте ложно, но портит отставание ()
- 11 выключается — в этом контексте ложно, но портит отставание ()
- 11 включается -- OK, новая последовательность, включить в SELECT
- 10 включено -- OK, новая последовательность, включить в SELECT
- 11 выключается -- сообщение пришло с опозданием, нужно игнорировать пробел
- 10 выключается -- ОК, правильное OFF для строки 4, необходимо включить в SELECT
После правильной фильтрации я хотел бы использовать lead()
сверху всего этого, чтобы получить идентификатор следующей строки (представьте себе отметку времени), а также отфильтровать все записи, которые не являются ON
статусами. Я предполагаю, что для этого потребуются три встроенных оператора SELECT. Это дало бы мне четкое представление о том, как долго устройство было активным, до состояния другого ON
или правильного поворота OFF
.