Одним из вариантов является использование оконных функций.Используйте lag
, чтобы получить предыдущее значение состояния (на основе указанного порядка), сравнить его со значением текущей строки и назначить группы с промежуточной суммой.Затем подсчитайте значения в каждой группе и, наконец, отфильтруйте по этому условию.
SELECT t.*
FROM
( SELECT t.*,
count(*) over(PARTITION BY mail, grp) AS grp_count
FROM
( SELECT t.*,
sum(CASE
WHEN (prev_status IS NULL AND status='FAILED') OR
(prev_status='FAILED' AND status='FAILED') THEN 0
ELSE 1
END) over(PARTITION BY mail ORDER BY "date","transaction") AS grp
FROM
( SELECT t.*,
lag(status) over(PARTITION BY mail ORDER BY "date","transaction") AS prev_status
FROM tbl t
) t
) t
) t
WHERE grp_count>=4
Если вы используете версии, начинающиеся с Oracle 12c, есть опция для использования MATCH_RECOGNIZE
, которая упростит это.
select *
from tbl
MATCH_RECOGNIZE (
PARTITION BY mail
ORDER BY "date" ,"transaction"
ALL ROWS PER MATCH
AFTER MATCH SKIP TO LAST FAIL
PATTERN(fail{4,})
DEFINE
fail AS (status='FAILED')
) MR
ORDER BY "date","transaction"