The problem: given a table where a column value marks a boundary, select all sequential rows between boundaries.
An example case:
Suppose you have several devices logging measurements into a table. Suppose also that these devices are known to malfunction, and send an erroneous signal every now and then. Once we receive an erroneous signal, we should mark those rows as suspicious, until we receive another erroneous signal (which means the device has become stable again).
Example fiddle: https://www.db-fiddle.com/f/4jyoMCicNSZpjMt4jFYoz5/5247
In our example, the erroneous signal (marked by value 99) separates the dataset as:
- Device A - Lines 1-8: good
- Device A - Lines 9-14: suspicious
- Device A - Lines 15-17: good
- Device A - Lines 18-23: suspicious
- Device B - Lines 24++: good
I'd like to mark rows 9-14 and 18-23 as suspicious. Can this be done using pure SQL, without resorting to cursors?
What I've tried:
with d as (
select *,
CASE
WHEN v=99 THEN 1
ELSE 0
END as mark
FROM test
),
d2 as (
SELECT *,
DENSE_RANK() OVER (PARTITION BY device,mark ORDER BY t) as r
FROM d
)
SELECT *
FROM d2
ORDER BY device,t;
Close, but no cigar. The r(anking) column isn't match of a help.
PS: I tried to make this as generic as possible in order to be useful for other users as well. I think it should be a pretty common problem.