Odpowiedź na zaktualizowane pytanie
SELECT *
FROM (
SELECT *
,lag(val, 1, 0) OVER (PARTITION BY status ORDER BY id) last_val
,lag(status) OVER (PARTITION BY val ORDER BY id) last_status
FROM t1
) x
WHERE status = 1
AND (last_val <> val OR last_status = 0)
Jak?
Tak samo jak poprzednio, ale tym razem łączymy dwie funkcje okna. Włączenie urządzenia kwalifikuje się, jeśli ..
1. ostatnie włączone urządzenie było inne jeden.
2. lub to samo urządzenie zostało wyłączone w swoim ostatnim wpisie. Przypadek narożny z NULL
dla pierwszego wiersza partycji nie ma znaczenia, ponieważ wtedy wiersz został już zakwalifikowany w 1.
Odpowiedź na oryginalną wersję pytania.
Jeśli dobrze rozumiem Twoje zadanie, to proste zapytanie wykona zadanie:
SELECT *
FROM (
SELECT *
,lag(val, 1, 0) OVER (ORDER BY id) last_on
FROM t1
WHERE status = 1
) x
WHERE last_on <> val
Zwraca wiersze 1, 3, 6, 7 zgodnie z żądaniem.
Jak?
Podzapytanie ignoruje wszystkie wyłączenia, ponieważ to tylko szum, zgodnie z twoim opisem. Pozostawia wpisy, w których urządzenie jest włączone. Wśród nich dyskwalifikowane są tylko te wpisy, na których to samo urządzenie było już włączone (włączony ostatni wpis). Użyj funkcji okna lag()
za to. W szczególności podaję 0
domyślnie obejmuje specjalny przypadek pierwszego wiersza - zakładając, że nie ma urządzenia z val = 0
.
Jeśli istnieje, wybierz inną niemożliwą liczbę.
Jeśli żadna liczba nie jest niemożliwa, pozostaw specjalny przypadek jako NULL
z lag(val) OVER ...
a w zewnętrznym zapytaniu sprawdź za pomocą:
WHERE last_on IS DISTINCT FROM val