我有一个数据库表,该表的列的值在1到999之间 但是它有一些空间,例如1,2,3,4,5,6,11,15等...
从该表中获取“下一个号码”最好是什么?
预先感谢您的帮助
答案 0 :(得分:2)
执行此操作的一种方法是获取每一行的前一行,然后检查要执行的步骤。
这将不能很好地执行,并且当有1个以上的用户正在添加新行时,这不是安全的!
declare @t table (number int)
insert into @t values (1), (2), (3), (4), (5), (6), (11), (12)
select top 1
(select top 1 t2.number + 1 from @t t2 where t2.number < t.number order by t2.number desc) as prior
from @t t
where number <> (select top 1 t2.number + 1 from @t t2 where t2.number < t.number order by t2.number desc)
order by t.number
结果将是7
这是另一个选择
select top 1
t.number + 1
from @t t
left join @t t2 on t.number = t2.number - 1
where t2.number is null
order by t.number
此方法甚至可能比Robin的解决方案更快
编辑
正如丹尼尔(Daniel)在评论中指出的那样,如果空白恰好是第一行,则它将永远不会返回1
。
要解决此问题,我们可以为缺少的第一行检索一个值,并通过使用并集将其添加到我们的结果中。
select top 1 number
from ( select top 1
t.number + 1 as number
from @t t
left join @t t2 on t.number = t2.number - 1
where t2.number is null
union
select 1 as number
from @t t
where not exists (select 1 from @t t3 where t3.number = 1)
) t
order by t.number
由于额外的查询只能按索引检索确切的一行,因此不会对性能产生太大影响
答案 1 :(得分:1)
您可以使用CTE生成数字,然后获取与记录不匹配的第一个数字。...
如您所言,它不是一张大桌子,效果很好
我有一个数据表,其中的列的值在1到999之间
关于其他答案,两个答案都比大型表的答案要快得多,但是如果您的输入从2或更大开始,则没有一个答案会返回正确的值(1)。
我不知道此请求的目的,但是请注意,以这种方式计算值的两个用户同时工作可以得到相同的值。如果您想将此值用作主键或唯一索引的一部分
;with numbers as (
SELECT 1 as nrstart, MAX(yourcolumn) as nrend FROM yourTable
UNION ALL
SELECT nrstart+1, nrend FROM numbers
WHERE nrstart <= nrend
)
SELECT TOP 1 nrstart
FROM numbers
WHERE NOT EXISTS (SELECT 1 FROM yourTable WHERE yourcolumn = numbers.nrstart)
ORDER BY nrStart
OPTION (MAXRECURSION 0);
答案 2 :(得分:0)
您需要第一个数字,该数字加一个不在表中。
SELECT TOP 1 (Number + 1) FROM myTable a WHERE NOT EXISTS
(SELECT * FROM myTable b WHERE b.Number = a.Number + 1)
ORDER By Number
正如各种评论中所提到的那样,如果第二位用户在寻找缺口的同时存在第二位用户填补缺口的风险,则应在事务中完成这种事情。