Как запросом определить нарушение последовательности?

Есть последовательность записей, у которых в поле А записаны числа. Нормальный вид этой последовательности - непрерывная (1, 2, 3, 4, 5).

Как определить с помощью запроса, нарушена ли последовательность или нет?

Пример нарушения последовательности: (1, 2, 4, 5, 7), либо (1, 2, 2, 3, 4).

Думал как-то через факториал подойти к решению, но не осилил. Может есть у кого-то соображения по поводу решения?


PS Предложеный дубликат не учитывает повторяющиеся значения.


Ответы (2 шт):

Автор решения: Akina

последовательность начинается с 0 – Анатолий Эрнст

WITH cte AS ( SELECT number, ROW_NUMBER() OVER (ORDER BY number) - 1 rn
              FROM table )
SELECT EXISTS ( SELECT NULL
                FROM cte
                WHERE number <> rn ) AS not_consecutive
→ Ссылка
Автор решения: 0xdb

Разница между текушим значением последовательности и порядковым номером записи всегда одно и тоже число, неважно с какого числа начинается отсчёт. Если в результате несколько таких чисел, то где-то есть нарушение последовательности.

Рабочий пример:

with t (seq, num) as (
    select 'seq1', column_value from sys.odciNumberList (1, 2, 3, 4, 5) n union all  
    select 'seq2', column_value from sys.odciNumberList (1, 2, 4, 5, 7) n union all  
    select 'seq3', column_value from sys.odciNumberList (1, 2, 2, 3, 4) n union all  
    select 'seq4', column_value from sys.odciNumberList (0, 1, 2, 3, 4) n
) 
select seq, case when count (distinct grp)=1 then 'yes' else 'no' end consecutive
from (
    select seq, num - row_number() over (partition by seq order by num) grp
    from t)
group by seq
order by seq

Результат:

SEQ  CONSECUTIVE 
---- ------------
seq1 yes         
seq2 no          
seq3 no          
seq4 yes 

Если версия 12c и выше, то задачу можно решить с клаузой MATCH_RECOGNIZE:

select seq, case when count (*)=1 then 'yes' else 'no'end consecutive
from t
match_recognize (
    partition by seq
    order by num
    measures null grp 
    pattern (a b*)
    define b as num = prev (num)+1
) group by seq;

SEQ  CONSECUTIVE 
---- ------------
seq1 yes         
seq2 no          
seq3 no          
seq4 yes         
→ Ссылка