Jawaban untuk pertanyaan yang diperbarui
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)
Bagaimana?
Sama seperti sebelumnya, tetapi kali ini menggabungkan dua fungsi jendela. Mengaktifkan perangkat memenuhi syarat jika ..
1. perangkat terakhir yang diaktifkan adalah berbeda satu.
2. atau perangkat yang sama telah mati dalam entri terakhirnya. Kasus sudut dengan NULL
untuk baris pertama partisi tidak relevan, karena baris tersebut sudah memenuhi syarat di 1.
Jawaban untuk versi asli pertanyaan.
Jika saya memahami tugas Anda dengan benar, kueri sederhana ini berhasil:
SELECT *
FROM (
SELECT *
,lag(val, 1, 0) OVER (ORDER BY id) last_on
FROM t1
WHERE status = 1
) x
WHERE last_on <> val
Mengembalikan baris 1, 3, 6, 7 seperti yang diminta.
Bagaimana?
Subquery mengabaikan semua penonaktifan, karena itu hanya noise, menurut deskripsi Anda. Meninggalkan entri di mana perangkat diaktifkan. Di antara mereka, hanya entri yang didiskualifikasi, di mana perangkat yang sama sudah menyala (entri terakhir diaktifkan). Gunakan fungsi jendela lag()
untuk itu. Secara khusus saya memberikan 0
sebagai default untuk menutupi kasus khusus dari baris pertama - dengan asumsi bahwa tidak ada perangkat dengan val = 0
.
Jika ada, pilih nomor lain yang tidak mungkin.
Jika tidak ada nomor yang tidak mungkin, tinggalkan kasus khusus sebagai NULL
dengan lag(val) OVER ...
dan di kueri luar, periksa dengan:
WHERE last_on IS DISTINCT FROM val