Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何在表字段中查找从参数开始并按顺序递增的缺失数字?_Sql_Sql Server_Performance_Sequence - Fatal编程技术网

Sql 如何在表字段中查找从参数开始并按顺序递增的缺失数字?

Sql 如何在表字段中查找从参数开始并按顺序递增的缺失数字?,sql,sql-server,performance,sequence,Sql,Sql Server,Performance,Sequence,假设我有一个sql server表: 数字肯公司名称 2弗雷德3弗雷德4弗雷德6弗雷德7弗雷德8弗雷德11弗雷德 我需要一种有效的方法来传入参数[StartingNumber],并从[StartingNumber]开始按顺序计数,直到找到缺少的数字 例如,请注意表中缺少1、5、9和10 如果我提供了参数[StartingNumber]=1,它将检查1是否存在,如果存在,它将检查2是否存在,依此类推,因此这里将返回1 如果[StartNumber]=6,函数将返回9 在c伪代码中,它基本上是: i

假设我有一个sql server表:

数字肯公司名称

2弗雷德3弗雷德4弗雷德6弗雷德7弗雷德8弗雷德11弗雷德

我需要一种有效的方法来传入参数[StartingNumber],并从[StartingNumber]开始按顺序计数,直到找到缺少的数字

例如,请注意表中缺少1、5、9和10

如果我提供了参数[StartingNumber]=1,它将检查1是否存在,如果存在,它将检查2是否存在,依此类推,因此这里将返回1

如果[StartNumber]=6,函数将返回9

在c伪代码中,它基本上是:

int ctr = [StartingNumber]
while([SELECT NumberTaken FROM tblNumbers Where NumberTaken = ctr] != null)    
    ctr++;

return ctr;
该代码的问题是,如果表中有数千个数字,那么它看起来效率很低。此外,我可以用c代码或存储过程编写它,以更高效的为准


感谢您的帮助

尝试基于集合的方法-应该更快

select min(t1.NumberTaken)+1 as "min_missing" from t t1
where not exists (select 1 from t t2 
                   where t1.NumberTaken = t2.NumberTaken+1)
and t1.NumberTaken > @StartingNumber
这是Sybase语法,因此如果需要,可以针对SQL server消费进行按摩。

使用JOIN的解决方案:


我将我的表格称为空白,并使用以下命令:

declare @StartOffset int = 2
; With Missing as (
    select @StartOffset as N where not exists(select * from Blank where ID = @StartOffset)
), Sequence as (
    select @StartOffset as N from Blank where ID = @StartOffset
    union all
    select b.ID from Blank b inner join Sequence s on b.ID = s.N + 1
)
select COALESCE((select N from Missing),(select MAX(N)+1 from Sequence))
基本上有两种情况-要么缺少起始值,因此缺少的CTE将包含一行,要么存在,因此使用递归CTE序列向前计数,并从中取最大值,然后加1

从评论中编辑。是的,在顶部创建另一个包含筛选条件的CTE,然后在查询的其余部分使用该CTE:

declare @StartOffset int = 2
; With BlankFilters as (
    select ID from Blank where hasEntered <> 1
), Missing as (
    select @StartOffset as N where not exists(select * from BlankFilters where ID = @StartOffset)
), Sequence as (
    select @StartOffset as N from BlankFilters where ID = @StartOffset
    union all
    select b.ID from BlankFilters b inner join Sequence s on b.ID = s.N + 1
)
select COALESCE((select N from Missing),(select MAX(N)+1 from Sequence))

创建一个临时表,其中包含从起始值到结束值的所有数字,并将左外连接到数据表。

我将查询更改为从[QUEUE]q中选择q.NumberTake+1如果不存在,请从[QUEUE]q2中选择q2.NumberTake,其中q2.NumberTake=q.NumberTake+1我有一个小问题,我需要它从1开始计数,因此,例如,如果上面的表缺少第一行Numbertaken[1],它需要返回1。有什么想法吗?好的,我有一个小问题,我需要它从1开始计数,因此,例如,如果上面的表格缺少第一行数字,那么它需要返回1。有什么想法吗?用union代替r1,比如从r1中选择numbertaken union 0作为x或其他什么。嘿,谢谢你的回答,我试图关闭副本,但它不允许我。我还有一个问题,假设我想在查询表之前对其进行过滤,例如,如果“Blank”有一个额外的字段“hasnenter”,并且我只想在“hasnenter”1的字段上运行您的查询,是否可以在不生成临时表的情况下执行此操作?
declare @StartOffset int = 2
; With BlankFilters as (
    select ID from Blank where hasEntered <> 1
), Missing as (
    select @StartOffset as N where not exists(select * from BlankFilters where ID = @StartOffset)
), Sequence as (
    select @StartOffset as N from BlankFilters where ID = @StartOffset
    union all
    select b.ID from BlankFilters b inner join Sequence s on b.ID = s.N + 1
)
select COALESCE((select N from Missing),(select MAX(N)+1 from Sequence))
create table Blank (
    ID int not null,
    Name varchar(20) not null
)
insert into Blank(ID,Name)
select 2 ,'Fred' union all
select 3 ,'Fred' union all
select 4 ,'Fred' union all
select 6  ,'Fred' union all
select 7 ,'Fred' union all
select 8 ,'Fred' union all
select 11 ,'Fred'
go