2014-10-27 66 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