복붙노트

[SQL] SQL 서버에서 가장 작은 사용되지 않는 번호 찾기

SQL

SQL 서버에서 가장 작은 사용되지 않는 번호 찾기

당신은 어떻게 SQL 서버 열에서 가장 작은 사용하지 않는 번호를 찾을 수 있습니까?

나는 SQL Server 테이블에 엑셀에서 수동으로 기록 된 많은 수의 레코드를 가져 오는에 대해 생각합니다. 지금부터 내 웹 사이트가 새 레코드를 기록하는 경우에 의미, 그들은 모두 숫자 ID (라는 문서 번호)를 가지고 있지만, 그들은 더 이상이 적용된다는 이유로 순차적으로 할당되지되지 않은, 그것은 (그에게 가능한 가장 작은 문서 번호를 할당 할 필요가 이미 사용되지 않은 0보다 큰).

일반 SQL을 통해이 할 수있는 방법이 있나요 또는이 TSQL / 코드에 대한 문제?

감사!

편집하다

동시성의 문제를 제기하기위한 WW 특별 감사. 이 웹 응용 프로그램임을 감안할 때, 충돌을 방지하기 위해 코드 또는 DB 수준 잠금 중 하나를 고려해야 멀티 스레드 정의와이 같은 문제에 직면 사람입니다.

LINQ

참고 -이 다음 코드를 사용하여 LINQ를 통해 수행 할 수 있습니다 :

var nums = new [] { 1,2,3,4,6,7,9,10};

int nextNewNum = (
    from n in nums
    where !nums.Select(nu => nu).Contains(n + 1)
    orderby n
    select n + 1
).First();

nextNewNum == 5

해결법

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

    1.+ 1 ID로 행이 존재하지 않는 첫 번째 행을 찾기

    + 1 ID로 행이 존재하지 않는 첫 번째 행을 찾기

    SELECT TOP 1 t1.Id+1 
    FROM table t1
    WHERE NOT EXISTS(SELECT * FROM table t2 WHERE t2.Id = t1.Id + 1)
    ORDER BY t1.Id
    

    편집하다:

    가장 낮은 기존의 ID가 여기에, 1이 아닌 추한 솔루션이다 특별한 경우를 처리하려면 :

    SELECT TOP 1 * FROM (
        SELECT t1.Id+1 AS Id
        FROM table t1
        WHERE NOT EXISTS(SELECT * FROM table t2 WHERE t2.Id = t1.Id + 1 )
        UNION 
        SELECT 1 AS Id
        WHERE NOT EXISTS (SELECT * FROM table t3 WHERE t3.Id = 1)) ot
    ORDER BY 1
    
  2. ==============================

    2.당신이 숫자 ID별로 정렬하는 경우, 당신이 찾고있는 수는 ROW_NUMBER () 함수는 ID와 동일하지 않습니다하는 최초의 하나가 될 것입니다.

    당신이 숫자 ID별로 정렬하는 경우, 당신이 찾고있는 수는 ROW_NUMBER () 함수는 ID와 동일하지 않습니다하는 최초의 하나가 될 것입니다.

  3. ==============================

    3.지금까지 답변의에서 잠금이나 동시성에 대한 언급이 없습니다.

    지금까지 답변의에서 잠금이나 동시성에 대한 언급이 없습니다.

    이 두 사용자가 거의 같은 시간에 문서를 추가하는 것을 고려 : -

    User 1                User 2
    Find Id               
                          Find Id
    Id = 42               
                          Id = 42
    Insert (42..)  
                          Insert (42..)
                          Error!
    

    당신이 중 하나를해야합니다 A) 그 오류를 처리하고 다음 사용 가능한 아이디를 찾고 다시 루프를 돌아 다니면서, OR b)는 이렇게 단 1 사용자가 특정 시간에 ID를 찾고있는 과정의 시작에 잠금을 꺼내

  4. ==============================

    4.

    SELECT TOP 1 t1.id+1
    FROM mytable t1
     LEFT OUTER JOIN mytable t2 ON (t1.id + 1 = t2.id)
    WHERE t2.id IS NULL
    ORDER BY t1.id;
    

    이 @Jeffrey Hantlin 및 @Darrel 밀러에 의해 주어진 상관 하위 쿼리를 사용하여 답변에 대한 대안입니다.

    그러나이 설명하고있는 정책은 정말 좋은 생각이 아니다. ID 값은 고유해야하지만, 연속적 일 필요가되어서는 안된다.

    당신은 # 42, 문서에 대한 링크와 함께 사람을 이메일을 보내 다음 나중에 문서를 삭제하면 어떻게됩니까? 나중에 새 문서의 ID 번호 (42)를 다시 사용합니다. 이제 전자 메일의 수신자가 잘못된 문서에 대한 링크를 따를 것이다!

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

    5.

    declare @value int
    
    select @value = case 
                      when @value is null or @value + 1 = idcolumn 
                        then idcolumn 
                      else @value end
       from table
       order by idcolumn
    
    select @value + 1
    

    1 표 2 스캔 해시 일치보다는 스캔합니까 그리고 상단의 대답처럼 가입

  6. ==============================

    6.간격이 순서가있는 경우, 당신은 이런 일에 최초의 차이를 찾을 수 있습니다 :

    간격이 순서가있는 경우, 당신은 이런 일에 최초의 차이를 찾을 수 있습니다 :

    select top 1 (found.id + 1) nextid from (select id from items union select 0) found
        where not exists (select * from items blocking
                              where blocking.id = found.id + 1)
        order by nextid asc
    

    즉, 그의 후계자 존재하지 않는 최소한의 ID를 발견하고, 그 후임을 반환합니다. 틈이 없을 경우, 가장 큰 현존하는 ID에 1을 더한를 반환합니다. 0 틀 ID는 1로 시작하는 ID가 고려되는 것을 보장하기 위해 삽입된다.

    이 적어도 N 로그 N 시간이 걸릴 수 있습니다.

    당신은 절차 적 코드에 의존 할 필요가 없습니다 수 있도록 마이크로 소프트 SQL은 삽입 문에 절에서의 사용을 허용한다.

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

    7.그것은 가능한 가장 작은 수를이어야하는 이유가 있나요? 왜 구멍을 작성해야합니까?

    그것은 가능한 가장 작은 수를이어야하는 이유가 있나요? 왜 구멍을 작성해야합니까?

    광고에 편집 대답은 비즈니스 규칙은 이후.

    DECLARE @counter int
    DECLARE @max
    SET @counter = 0
    SET @max = SELECT MAX(Id) FROM YourTable
    WHILE @counter <= @max
    BEGIN
        SET @counter = @counter + 1
        IF NOT EXISTS (SELECT Id FROM YourTable WHERE Id = @counter)
            BREAK
        END
    END
    

    (이 100 % 정확하지 않을 수 있습니다 그래서는 DB 편리하지 않습니다,하지만 당신은 거기에서 그것을 얻을 수있을 것입니다)

  8. ==============================

    8.

    select
        MIN(NextID) NextUsableID
    from (
        select (case when c1 = c2 then 0 
                else c1 end) NextID 
        from (  select ROW_NUMBER() over (order by record_id) c1, 
                       record_id c2
                from   myTable)
    )
    where NextID > 0
    
  9. ==============================

    9.다음은 간단한 방법이다. 그것은 더 빨리하지 않을 수 있습니다. 그것은 처음에 번호가 누락 찾을 수 없습니다.

    다음은 간단한 방법이다. 그것은 더 빨리하지 않을 수 있습니다. 그것은 처음에 번호가 누락 찾을 수 없습니다.

    SELECT MIN(MT1.MyInt+1)
    FROM MyTable MT1
    LEFT OUTER JOIN MyTable MT2 ON (MT1.MyInt+1)=MT2.MyInt
    WHERE MT2.MyInt Is Null
    
  10. ==============================

    10.이제 당신의 ID를 항상 1로 시작해야 가정 해 봅시다 :

    이제 당신의 ID를 항상 1로 시작해야 가정 해 봅시다 :

    SELECT MIN(a.id) + 1 AS firstfree
    FROM (SELECT id FROM table UNION SELECT 0) a
    LEFT JOIN table b ON b.id = a.id + 1
    WHERE b.id IS NULL
    

    전혀 기존 레코드를 포함하여 - 이것은 내가 생각할 수있는 모든 경우를 처리합니다.

    나는이 솔루션에 대해 좋아하지 않는 유일한 것은 추가 조건 그렇게 두 번 포함해야한다는 것입니다 :

    SELECT MIN(a.id) + 1 AS firstfree
    FROM (SELECT id FROM table WHERE column = 4711 UNION SELECT 0) a
    LEFT JOIN table b ON b.column = 4711 AND b.id = a.id + 1
    WHERE b.id IS NULL
    

    채우기 격차에 대한 요구 사항은 대부분의 경우에 나쁜 디자인과 문제가 발생할 수 있습니다 - 또한 잠금 및 동시성에 대한 의견을주의하시기 바랍니다. 그러나, 나는 그것을 할 수있는 좋은 이유가 있었다 다음 ID를 인쇄하고 인간에 의해 입력 할 수있는 모든 저 사람이없는 동안 우리는 약간의 시간이 지나면 많은 자리 ID를하고 싶지 않아 ...

  11. ==============================

    11.당신은 정말 IDENTITY에 열을 변환하려고합니다. 그들은 문서 수 1로부터 시작 있도록 BACKUP은 먼저 문서 ID를 업데이트 할 ROW_NUMBER를 사용합니다. 숫자 열이 다른 테이블 (외래 키) 참조로 사용하는 경우 때문에 SQL Server는 외래 키를 업데이트하려고 어쩌면 충돌 때문에 실패 시점에서 WHILE 하나에서 수행해야합니다. 결국 단지 열의 정체성 사양을 수 있습니다.

    당신은 정말 IDENTITY에 열을 변환하려고합니다. 그들은 문서 수 1로부터 시작 있도록 BACKUP은 먼저 문서 ID를 업데이트 할 ROW_NUMBER를 사용합니다. 숫자 열이 다른 테이블 (외래 키) 참조로 사용하는 경우 때문에 SQL Server는 외래 키를 업데이트하려고 어쩌면 충돌 때문에 실패 시점에서 WHILE 하나에서 수행해야합니다. 결국 단지 열의 정체성 사양을 수 있습니다.

    : 그것은 더 많은 작업을 이제하지만 나중에 당신에게 문제를 많이 절약 할 수 있습니다.

  12. ==============================

    12.나는이 대답은 늦게 알고하지만 당신은 재귀 테이블 식을 사용하여 최소 사용되지 않는 번호를 찾을 수 있습니다 :

    나는이 대답은 늦게 알고하지만 당신은 재귀 테이블 식을 사용하여 최소 사용되지 않는 번호를 찾을 수 있습니다 :

    CREATE TABLE Test
    (
        ID int NOT NULL
    )
    
    --Insert values here
    
    ;WITH CTE AS
    (
        --This is called once to get the minimum and maximum values
        SELECT nMin = 1, MAX(ID) + 1 as 'nMax' 
        FROM Test
        UNION ALL
        --This is called multiple times until the condition is met
        SELECT nMin + 1, nMax 
        FROM CTE
        WHERE nMin < nMax
    )
    
    --Retrieves all the missing values in the table. Removing TOP 1 will
    --list all the unused numbers up to Max + 1
    SELECT TOP 1 nMin
    FROM CTE
    WHERE NOT EXISTS
    (
        SELECT ID
        FROM Test
        WHERE nMin = ID
    )
    
  13. ==============================

    13.나는 비슷한 문제에 직면하고이 함께했다 :

    나는 비슷한 문제에 직면하고이 함께했다 :

    Select Top 1 IdGapCheck
    From (Select Id, ROW_NUMBER() Over (Order By Id Asc) AS IdGapCheck
        From dbo.table) F
    Where Id > IdGapCheck
    Order By Id Asc
    
  14. ==============================

    14.오라클 DB의 경우이 작업을 수행해야합니다

    오라클 DB의 경우이 작업을 수행해야합니다

    SELECT MIN(NI) FROM
            (SELECT ROWNUM AS NI,YOUR_ID
             FROM (SELECT YOUR_ID
                   FROM YOUR_TABLE 
                   ORDER BY YOUR_ID ASC))
    WHERE NI<>YOUR_ID
    
  15. ==============================

    15.ROW_NUMBER () 함수의 예 :

    ROW_NUMBER () 함수의 예 :

    IF NOT 존재  FROM (SELECT TOP 1 ROW_NUM     t (표 FROM ROW_NUMBER () OVER (ORDER BY 이드) ROW_NUM 이드 해당)        WHERE t.Id> t.row_num) SELECT MAX (ID) 테이블에서 +1  FROM ELSE SELECT TOP 1 ROW_NUM         t (표 FROM ROW_NUMBER () OVER (ORDER BY 이드) ROW_NUM 이드 해당)            WHERE t.Id> t.row_num;

  16. from https://stackoverflow.com/questions/684106/find-the-smallest-unused-number-in-sql-server by cc-by-sa and MIT license