SQL Server 2005 - 查找范围内的最小未使用值

时间:2010-04-23 19:05:40

标签: sql sql-server sql-server-2005

我的情况类似于以下问题:

Insert Data Into SQL Table

我的场景不同之处在于我有一个非自动递增的主键字段,其范围可以在1000到1999之间。到目前为止我们只有大约一百个值,但是已经取得了最大值(1999),编号顺序存在差距。因此,我需要找到一个介于1000-1999之间但未采用的值。例如,如果我的当前值是,例如,1000,1001,1003和1999,我希望查询返回1002。

6 个答案:

答案 0 :(得分:5)

试试这个:

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)

修改
这将得到相同的结果:

;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 :(得分:1)

我能想到的最简单的方法是创建一个值为1000-1999的表,然后执行以下操作:

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

但其他人可能会提出更优雅的解决方案

答案 2 :(得分:1)

编辑:看起来像KM打败我...使用他的解决方案。

我有一个不同的答案可能比我的另一个好。

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的最低数字。

答案 3 :(得分:1)

我不太确定我是否误解了这个问题,但看看像

这样的东西
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 - )。

答案 4 :(得分:1)

即使所选范围内没有记录,也会产生正确的答案。这也允许按字段分组以按组获得一组最低值。此示例中的SKU是指序号。

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替换为允许值最高的值。

答案 5 :(得分:1)

How do I find a "gap" in running counter with 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