2014-10-27 31 views
0

想象一下,有一个表,如下一个:查找自动递增值差距

create table test (
    id int auto_increment, 
    some int, 
    columns int 
) 

,然后得到使用这个表了很多。行被插入并且行被删除,并且随着时间的推移,可能会有数字中的差距一度被自动递增。举个例子,如果我在某些时候做下面的查询:

select top 10 id from test 

我可能会像

3 
4 
6 
7 
9 
10 
13 
14 
18 
19 

如何设计出返回遗漏值1,2,5查询, 8等?

+0

看看这篇文章:https://www.simple-talk.com/sql/t-sql-programming/the-sql-of-gaps-and-islands-in-sequences/ – Milen 2014-10-27 11:39:48

+0

什么版本您正在使用SQL Server? – 2014-10-27 11:40:31

回答

0

最简单的方法是让范围缺失值

select (id + 1) as firstmissing, (nextid - 1) as lastmissing 
from (select t.id, lead(id) over (order by id) as nextid 
     from test t 
    ) t 
where nextid is not null and nextid <> id + 1; 

注意这里使用了lead()功能,这是SQL Server 2012+可用。您可以在apply或早期版本的子查询中执行类似的操作。这里有一个例子:

select (id + 1) as firstmissing, (nextid - 1) as lastmissing 
from (select t.id, tt.id as nextid 
     from test t cross apply 
      (select top 1 id 
      from test t2 
      where t2.id > t.id 
      order by id 
      ) tt 
    ) t 
where nextid is not null and nextid <> id + 1; 
+0

你先生,真棒。谢谢! – Dave 2014-10-27 13:15:56

0

简单的方法是使用CTE ..

;WITH cte 
    AS (SELECT 1 id 
     UNION ALL 
     SELECT id + 1 id from cte 
     WHERE id < (SELECT Max(id) 
         FROM tablename)) 
SELECT * 
FROM cte 
WHERE id NOT IN(SELECT id 
       FROM tablename) 

注:这将从1.如果您想从表中的最小值开始只需更换启动

"SELECT 1 id" to "SELECT Min(id) id FROM tablename" 
0

它为什么重要?我并不是想表达自己的看法,但通常会在“我想填补空白”或“我想压缩我的id值连续”这样的背景下提出这个问题。无论哪种情况,答案都是“不要这样做”。在你的例子中,在某一时刻有一行id = 5的行。如果你打算做上述任何一项,你将分配一个不同的,不相关的业务数据集合,这些id是id。如果有任何引用数据库外部ID的东西,那么现在你已经发明了一个以前没有的问题。为了所有的意图和目的,该id应该被视为不可变和任意的。如果您确实需要它是无间隙的,请不要使用身份,也不要进行硬删除(即,如果您需要停用某一行,则需要一个表明其是否处于活动状态的列)。

+0

虽然我和你在一起,但这更多的是评论而不是回答。 – bummi 2014-10-27 13:56:31

+0

我认为,但这是一个普遍的问题,这是对这个问题的答案。并不是每一个问题都是技术问题。但是,如果您对此感到强烈,请使用向下箭头来带走我的一些互联网点。 – 2014-10-27 14:00:35

+0

既不标记也不投票只是注意 – bummi 2014-10-27 14:04:40