Найдите наименьшее неиспользуемое число в SQL Server

var visibilityChange = (function (window) {
    var inView = false;
    return function (fn) {
        window.onfocus = window.onblur = window.onpageshow = window.onpagehide = function (e) {
            if ({focus:1, pageshow:1}[e.type]) {
                if (inView) return;
                fn("visible");
                inView = true;
            } else if (inView) {
                fn("hidden");
                inView = false;
            }
        };
    };
}(this));

visibilityChange(function (state) {
    console.log(state);
});

http://jsfiddle.net/ARTsinn/JTxQY/

40
задан Community 23 May 2017 в 11:54
поделиться

9 ответов

Найдите первую строку, где там не существует строка с идентификатором + 1

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

Править:

Для обработки особого случая, где самый низкий существующий идентификатор не 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
57
ответ дан Darrel Miller 27 November 2019 в 00:16
поделиться

Действительно необходимо попытаться преобразовать столбец в ИДЕНТИФИКАЦИОННЫЕ ДАННЫЕ. СКОПИРУЙТЕ сначала затем использование ROW_NUMBER для обновления идентификатора документа, таким образом, они запускают от 1 и до количества документа. Необходимо выполнить в нем НЕКОТОРОЕ ВРЕМЯ один в то время, потому что, если столбец числа используется в качестве ссылки в других таблицах (внешние ключи), SQL Server попытается обновить внешние ключи и возможно перестать работать из-за конфликтов. В конце просто включают спецификации идентификационных данных для столбца.

:) Это - больше работы теперь, но это сохранит Вас большая проблема позже.

1
ответ дан Ovidiu Pacurar 27 November 2019 в 00:16
поделиться
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 Miller.

Однако политика, которую Вы описываете, является действительно не хорошей идеей. Значения идентификаторов должны быть уникальными, но не должны требоваться, чтобы быть последовательными.

Что происходит, если Вы посылаете кому-то по электронной почте со ссылкой на документ № 42 и затем впоследствии удаляете документ? Позже, Вы снова используете идентификатор № 42 для нового документа. Теперь получатель электронной почты перейдет по ссылке к неправильному документу!

10
ответ дан Bill Karwin 27 November 2019 в 00:16
поделиться

Если существуют разрывы в последовательности, можно найти первый разрыв с чем-то вроде этого:

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

Другими словами, найдите наименьшее количество идентификатора, преемник которого не существует, и возврат тот преемник. Если нет никаких разрывов, это возвращает одно большее, чем самый большой существующий идентификатор. Идентификатор заполнителя 0 вставляется, чтобы обеспечить, чтобы идентификаторы, запускающиеся с 1, рассмотрели.

Обратите внимание, что это возьмет, по крайней мере, n, регистрируют n время.

Microsoft SQL разрешает использование a from пункт в insert оператор, таким образом, Вы, возможно, не должны обращаться к процессуальному кодексу.

3
ответ дан Jeffrey Hantin 27 November 2019 в 00:16
поделиться

Никакое упоминание о блокировке или параллелизме в любом из ответов до сих пор.

Рассмотрите эти двух пользователей, добавляющих документ в почти то же время:-

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

Вы любой должны: a) Обрабатывают ту ошибку и обходят цикл, снова ища следующего доступного Id, Орегон b) Берут блокировку в начале процесса, таким образом, только 1 пользователь ищет Ids в определенное время

12
ответ дан WW. 27 November 2019 в 00:16
поделиться

При сортировке их по числовому идентификатору число, которое Вы ищете, будет первым, для которого ROW_NUMBER () функция не равняется идентификатору.

12
ответ дан MarkusQ 27 November 2019 в 00:16
поделиться

Существует ли причина, что это должно быть самое маленькое количество? Почему необходимо заполнить дыры?

Редактирование к рекламе ответ, так как это - бизнес-правило.

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% точно, но необходимо смочь получить его оттуда),

2
ответ дан Matt Grande 27 November 2019 в 00:16
поделиться
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
2
ответ дан 27 November 2019 в 00:16
поделиться
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, сканирует совпадение хэша и соединение, как верхний ответ

5
ответ дан 27 November 2019 в 00:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: