SQL Server 2005 - найдите минимальное неиспользуемое значение в диапазоне - PullRequest
4 голосов
/ 23 апреля 2010

У меня есть ситуация, похожая на следующий вопрос:

Вставка данных в таблицу SQL

Мой сценарий отличается тем, что у меня неинкрементныйполе первичного ключа, которое может иметь диапазон от 1000 до 1999. Пока у нас есть только около ста значений, но максимальное значение уже взято (1999), и в последовательности нумерации есть пробелы.Таким образом, мне нужно найти значение, которое находится между 1000-1999 и не взято.Например, если мои текущие значения, например, 1000, 1001, 1003 и 1999, я бы хотел, чтобы запрос возвратил 1002.

Ответы [ 6 ]

5 голосов
/ 23 апреля 2010

попробуйте это:

declare @YourTable table (PK int)
insert @YourTable VALUES (1)
insert @YourTable VALUES (2)
insert @YourTable VALUES (4)
insert @YourTable VALUES (7)
insert @YourTable VALUES (8)


SELECT
    MIN(y.PK)+1
    FROM @YourTable                 y
        LEFT OUTER JOIN @YourTable y2 ON y.PK+1=y2.PK 
    WHERE y.PK>=1 AND y.PK<10 AND y2.PK IS NULL

ВЫВОД:

-----------
3

(1 row(s) affected)

EDIT
это даст тот же результат:

;with N AS 
(SELECT TOP 1000 row_number() over(order by t1.object_id) as Number
     FROM sys.objects t1 
     CROSS JOIN sys.objects t2
)
SELECT
    MIN(Number) AS PK
    FROM N
        LEFT OUTER JOIN @YourTable y on n.Number=y.PK
    WHERE y.PK IS Null
1 голос
/ 02 июля 2013

из Как мне найти «пробел» в работе счетчика с SQL?

select
    MIN(ID)
from (
    select
        1000 ID
    union all
    select
        [YourIdColumn]+1
    from
        [YourTable]
    where
        --Filter the rest of your key--
    ) foo
left join
    [YourTable]
    on [YourIdColumn]=ID
    and --Filter the rest of your key--
where
    [YourIdColumn] is null
1 голос
/ 28 декабря 2010

Это дает правильный ответ, даже если в выбранном диапазоне нет записей. Это также позволяет группировать по полю, чтобы получить набор самых низких значений по группам. Артикул в этом примере относится к порядковым номерам.

SELECT    A.myType, 
          COALESCE (MIN( A.sku) + 1, 1) AS SKU /* 1 is Min Default + 1 */
FROM      (  SELECT  distinct myType, sku
             FROM    dbo.myTable AS p1
             where   p1.sku > 0       /* zero is Min Value */ 
                     and p1.sku < 100 /* 100 is Max Value */ 
             union 
             select  distinct myType, 0 as sku /* Guarantee Min Value */
             from    dbo.myTable as t1
          ) AS A 
          LEFT OUTER JOIN
          (  SELECT distinct myType, sku
             FROM   dbo.myTable AS p2
             where  p2.sku > 0         /* zero is Min Value */ 
                    and p2.sku < 100   /* 100 is Max Value */
             union 
             select distinct myType, 0 as sku  /* Guarantee Min Value */
             from   dbo.myTable as t2
          ) AS B 
          ON A.myType = B.myType AND 
             A.sku + 1 = B.sku
where     (B.sku IS NULL)
GROUP BY  A.myType

distinct на самом деле ускоряет запрос, даже если union уже делает distinct. Пока у вас есть индекс для myType и SKU, он должен быть мгновенным.

Очевидно, что вы можете заменить 0 на самые низкие и 100 на самые высокие допустимые значения.

1 голос
/ 23 апреля 2010

Не совсем уверен, если я неправильно понял вопрос, но посмотрите на что-то вроде

declare @YourTable table (PK int) 
insert @YourTable VALUES (1) 
insert @YourTable VALUES (2) 
insert @YourTable VALUES (4) 
insert @YourTable VALUES (7) 
insert @YourTable VALUES (8) 

SELECT  TOP 1
        *
FROM    @YourTable yt
WHERE   NOT EXISTS  (
                        SELECT  1 
                        FROM    @YourTable 
                        WHERE   yt.PK+1 = PK
                    )
ORDER BY yt.PK

Результаты в

PK
-----------
2

Откуда вы можете выбрать (2 + 1) X -).

1 голос
/ 23 апреля 2010

РЕДАКТИРОВАТЬ : Похоже, К.М. Ударь меня ... используй его решение.

У меня есть другой ответ, который может быть лучше, чем мой другой.

Select Min(Main1.Key)+1
From Main as Main1
Left Join Main as Main2 on Main1.Key+1=Main2.Key
Where Main2.Key is Null

Это найдет наименьшее число, у которого над номером нет другого.

1 голос
/ 23 апреля 2010

Самый простой способ, который я могу придумать, - это создать таблицу со значениями 1000-1999, а затем сделать следующее:

Select MIN(Values.Key)
From Main
Left Join Values on Values.Key = Main.Key
Where Main.Key is Null

Но кто-то другой, возможно, может предложить более элегантное решение

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...