简体   繁体   中英

Finding missing sequence numbers

I want to create a table to find missing sequence numbers. Sequence number between 0 to 70000 after reaching 70000 it becomes 0. In a particular period of time I need to find those missing records.

This solution is based on statement which generates all natural numbers from 1 to some limit you set:

SELECT ROWNUM N FROM dual CONNECT BY LEVEL <= 7000

Second part of this solution is Oracle MINUS operator (more commonly known as EXCEPT ), which is designed to subtract sets.

In other words, final query is:

SELECT ROWNUM id FROM dual CONNECT BY LEVEL <= 7000
MINUS
SELECT id FROM mytable

SQLFiddle demo for 20 numbers .

You may use Lead and lag functions to detect the gaps in the sequence.
The solution will not limit you for a specific upper bound number like 70000.

Detecting :

SELECT *
  FROM (SELECT lag(c.id) over(ORDER BY id) last_id,
               c.id curr_id,
               lead(c.id) over(ORDER BY id) next_id
          FROM mytable c
         order by id)
 WHERE nvl(last_id, curr_id) + 1 <> curr_id
   AND last_id IS NOT NULL

Sqlfiddle demo .

Traversing :

begin
  FOR x IN (SELECT *
              FROM (SELECT lag(c.id) over(ORDER BY id) last_id,
                           c.id curr_id,
                           lead(c.id) over(ORDER BY id) next_id
                      FROM mytable c order by id)
             WHERE nvl(last_id, curr_id) + 1 <> curr_id AND 
             last_id IS NOT NULL
            ) LOOP
    dbms_output.put_line('last_id :' || x.last_id);
    dbms_output.put_line('curr_id :' || x.curr_id);
    dbms_output.put_line('next_id :' || x.next_id);
    dbms_output.put('gaps found: ');
    for j in x.last_id + 1 .. nvl(x.next_id,x.curr_id) - 1   loop
      if  j != x.curr_id then
      dbms_output.put(j || ', ');
      end if;      
    end loop;
    dbms_output.put_line('');
    dbms_output.put_line('*****');
  end loop;
end;

I stole this from Tom Kyte a while ago:

select  id, one_before, Diff, dense_rank() over (order by Diff desc) rank from (
select  id, one_before,
            case when (id - one_before) > 1 then (id - one_before)
           else 1
           end Diff
 from (
       select id, lag(id) over(order by id) one_before
      from table_name order by id) )

The original discussion is located at http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:8146178058075 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM