복붙노트

[SQL] 어떻게 일련의 숫자에서 누락 된 번호를 확인하려면?

SQL

어떻게 일련의 숫자에서 누락 된 번호를 확인하려면?

나는 대학에 대한 입학 시스템을 만드는 프로젝트를하고있는 중이 야; 기술은 자바와 오라클입니다.

테이블 중 하나에서, 미리 생성 된 일련 번호가 저장된다. 나중에, 그 일련 번호에 대해, 신청자의 형태로 데이터가 입력됩니다. 내 요구 사항은 항목 프로세스가 완료되면 나는 많은 현명한 보고서를 생성 할 것입니다. 수유 중에 일련 번호를 미리 생성 된 경우 어떤 일련 번호가 누락 갔다.

예를 들어, 테이블, 시퀀스 번호는 7001, 7002, 7004, 7005, 7006, 7010를 말할. 위의 시리즈는 7001에서 7010에없는 숫자가 7003, 7007, 7008 및 7009를있는 것이 분명하다

어떤 DBMS가이 번호를 찾을 오라클에서 사용 가능한 기능이나 저장 프로 시저 내 목적을 달성 할 수있는 경우 다음 알고리즘을 제안 해주십시오있다.

나는 자바에 몇 가지 방법을 찾을 수 있지만 속도 나 오라클의 솔루션을 찾고 싶어요.

해결법

  1. ==============================

    1.9 하드 코딩없는 솔루션 :

    9 하드 코딩없는 솔루션 :

    select min_a - 1 + level
         from ( select min(a) min_a
                     , max(a) max_a
                  from test1
              )
      connect by level <= max_a - min_a + 1
        minus
       select a
         from test1
    

    결과 :

    MIN_A-1+LEVEL
    -------------
             7003
             7007
             7008
             7009
    
    4 rows selected.
    
  2. ==============================

    2.이 시도:

    이 시도:

    SELECT t1.SequenceNumber + 1 AS "From",
           MIN(t2.SequenceNumber) - 1 AS "To"
    FROM MyTable t1
    JOIN MyTable t2 ON t1.SequenceNumber < t2.SequenceNumber 
    GROUP BY t1.SequenceNumber
    HAVING t1.SequenceNumber + 1 < MIN(t2.SequenceNumber)
    

    여기서, 시퀀스 7001, 7002, 7004, 7005, 7006, 7010에 대한 결과이다 :

    From  To
    7003  7003
    7007  7009
    
  3. ==============================

    3.이 포스트 그레스> = 8.4에서 작동합니다. CTE에 구문에 약간의 수정으로 너무 오라클과 마이크로 소프트 작동하도록 만들어졌다.

    이 포스트 그레스> = 8.4에서 작동합니다. CTE에 구문에 약간의 수정으로 너무 오라클과 마이크로 소프트 작동하도록 만들어졌다.

    -- EXPLAIN ANALYZE
    WITH missing AS (
        WITH RECURSIVE fullhouse AS (
            SELECT MIN(num)+1 as num
            FROM numbers n0
            UNION ALL SELECT 1+ fh0.num AS num
            FROM fullhouse fh0
            WHERE EXISTS (
                    SELECT * FROM numbers ex
                    WHERE ex.num > fh0.num
                    )
            )
            SELECT * FROM fullhouse fh1
            EXCEPT ( SELECT num FROM numbers nx)
            )
    SELECT * FROM missing;
    
  4. ==============================

    4.시나리오에 대한 답변을 얻을 수있는 한 가지 간단한 방법이 있습니다 :

    시나리오에 대한 답변을 얻을 수있는 한 가지 간단한 방법이 있습니다 :

    create table test1 ( a number(9,0));
    
    insert into test1 values (7001);
    insert into test1 values (7002);
    insert into test1 values (7004);
    insert into test1 values (7005);
    insert into test1 values (7006);
    insert into test1 values (7010);
    commit;
    
    select n.n from (select ROWNUM + 7001 as n from dual connect by level <= 9) n 
       left join test1 t on n.n = t.a where t.a is null;
    

    선택은 당신에게 당신의 예에서 답을 줄 것이다. 이것은 단지 당신이 미리 알고있는 경우에하는 당신의 숫자는 그 범위해야 너무 크지 범위, 의미가 있습니다. 첫 번째 숫자는 상기 ROWNUM 부 오프셋되어야하며, 시퀀스의 길이 부에 의해 연결의 레벨로 제한된다.

  5. ==============================

    5.나는 스테판 완료했다 당신이 어떤 최대 및 최소 값을 알 필요로하지만, 당신이 당신을 위해 정말 적합하지 않은 것으로,이 성명에서하는 수단을 하위 쿼리를 사용할 수없는 수준으로 연결 제안 것이다 시퀀스입니다.

    나는 스테판 완료했다 당신이 어떤 최대 및 최소 값을 알 필요로하지만, 당신이 당신을 위해 정말 적합하지 않은 것으로,이 성명에서하는 수단을 하위 쿼리를 사용할 수없는 수준으로 연결 제안 것이다 시퀀스입니다.

    나는 파이프가 늘어선 테이블 기능을 사용하면 가입 할 필요가 숫자를 생성하는 가장 좋은 방법이 될 수 있습니다 제안합니다. 작업이 위해서는 당신에 값을 반환하는 데이터베이스에서 개체를 필요할 것 :

    create or replace type t_num_array as table of number;
    

    기능 다음 :

    create or replace function generate_serial_nos return t_num_array pipelined is
    
       l_first number;
       l_last number;
    
    begin
    
       select min(serial_no), max_serial_no)
         into l_first, l_last 
         from my_table
              ;
    
       for i in l_first .. l_last loop
          pipe row(i);
       end loop;
    
       return;
    
    end generate_serial_nos;
    /
    

    이 기능을 다음을 사용하여 최소 및 최대 사이에, 일련 번호의 목록을 반환합니다.

    select * from table(generate_serial_nos);
    

    어떤 쿼리가되고 일련 번호가 누락 된 찾을 것을 의미 :

    select serial_no
      from ( select * 
               from table(generate_serial_nos) 
                    ) generator 
      left outer join my_table actual
        on generator.column_value = actual.serial_no
     where actual.serial_no is null
    
  6. ==============================

    6.이 일을하지만 선택은 이후 첫번째 순서는 (시작 값) 전임자가 없습니다. SQL 서버에서 테스트하지만 오라클에서 작동합니다

    이 일을하지만 선택은 이후 첫번째 순서는 (시작 값) 전임자가 없습니다. SQL 서버에서 테스트하지만 오라클에서 작동합니다

    SELECT
        s.sequence  FROM seqs s
    WHERE
        s.sequence - (SELECT sequence FROM seqs WHERE sequence = s.sequence-1) IS NULL
    

    여기서 테스트 결과는

      Table
      -------------
      7000
      7001
      7004
      7005
      7007
      7008
    
      Result
      ----------
      7000
      7004
      7007
    

    할당 시퀀스를 얻기 위해서는, 단지 값을 [I] - 전 예컨대 큰 제 1 행을 (- 1 = 7003와 7007-7004 (7006) = 1) 서열을 이용할 수있다

    난 당신이 간단한 쿼리를 개선 할 수 있다고 생각

  7. ==============================

    7.여기에 솔루션이입니다 :

    여기에 솔루션이입니다 :

    SQL :

    WITH MentionedValues /*this would just be your actual table, only defined here to provide data for this example */
            AS (SELECT *
                  FROM (    SELECT LEVEL + 7000 seqnum
                              FROM DUAL
                        CONNECT BY LEVEL <= 10000)
                 WHERE seqnum NOT IN (7003,7007,7008,7009)--omit those four per example
                                           ),
         Ranges /*identifies all ranges between adjacent rows*/
            AS (SELECT seqnum AS seqnum_curr,
                       LAG (seqnum, 1) OVER (ORDER BY seqnum) AS seqnum_prev,
                       seqnum - (LAG (seqnum, 1) OVER (ORDER BY seqnum)) AS diff
                  FROM MentionedValues)
    SELECT Ranges.*,
           (    SELECT LISTAGG (Ranges.seqnum_prev + LEVEL, ',') WITHIN GROUP (ORDER BY 1)
                  FROM DUAL
            CONNECT BY LEVEL < Ranges.diff) "MissingValues" /*count from lower seqnum+1 up to lower_seqnum+(diff-1)*/
      FROM Ranges
     WHERE diff != 1 /*ignore when diff=1 because that means the numers are sequential without skipping any*/
    ;
    

    산출:

    SEQNUM_CURR SEQNUM_PREV DIFF MissingValues
    7004        7002        2    "7003" 
    7010        7006        4    "7007,7008,7009"                  
    
  8. ==============================

    8.

     SELECT ROWNUM "Missing_Numbers" FROM dual CONNECT BY LEVEL <= (SELECT MAX(a) FROM test1)
     MINUS
     SELECT a FROM test1 ;
    
  9. ==============================

    9.향상된 쿼리는 다음과 같습니다

    향상된 쿼리는 다음과 같습니다

    SELECT ROWNUM "Missing_Numbers" FROM dual CONNECT BY LEVEL <= (SELECT MAX(a) FROM test1)
     MINUS
    SELECT ROWNUM "Missing_Numbers" FROM dual CONNECT BY LEVEL < (SELECT Min(a) FROM test1)
     MINUS
    SELECT a FROM test1;
    

    참고 : 우리가 누락 가치를 찾을 수있는 열입니다.

  10. ==============================

    10.

     select    A.ID + 1 As ID
    From [Missing] As A
    Where A.ID + 1 Not IN (Select ID from [Missing])
    And A.ID < n
    
    Data: ID
    1
    2
    5
    7
    Result: ID
    3
    4
    6
    
  11. from https://stackoverflow.com/questions/10968493/how-to-check-any-missing-number-from-a-series-of-numbers by cc-by-sa and MIT license