在資料處理時,我們經常會使用一些「自增」的插入方式來處理資料。比如學生學號:b07051001,b07051002....類似的遞增關係的資料。
但是,如果中途因為某些原因將其中的一些記錄刪除掉之後,就會出現斷續的記錄。這時,我們可能期待將這些中間的缺失值再次利用。以下,就談談如何查詢最小缺失值。
首先,我們建乙個測試表:tb_test(主鍵並未設定為自增長):
create table tb_test ( id int primary key, val char(1) null )
插入一些資料:
insert into tb_test values(1,'a') insert into tb_test values(2,'b') insert into tb_test values(3,'c') insert into tb_test values(4,'d') insert into tb_test values(5,'e') insert into tb_test values(6,'f') insert into tb_test values(7,'g') insert into tb_test values(8,'h')
刪除某些記錄,製造「斷層」:
delete from tb_test where id in (1,2,4,5,7);
此時表中資料為不連貫的:
此時能看出最小缺失值應該為:1
我們通過下面這段sql能夠得到結果:
select
case
when not exists(select 1 from tb_test where id=1)
then 1
else (
select min(a.id+1)
from tb_test as a
where not exists
(select 1
from tb_test as b
where b.id=a.id+1))
end as '最小缺失值';
這裡使用了乙個小的技巧,原理是將表中所有記錄的id加1,再與源表中所有記錄的id匹配。這樣只要有源表中有id缺失,id+1在源表中就會有匹配不到的值。
比如源表中id序列為:1、2、3、5、7(a.id與b.id),則源表中的id+1序列為: 2、3、4、6、8(a.id+1);
這樣再代入子查詢中,就可以看到a.id+1=4,和a.id+1=6和a.id+1=8在b.id中不存在匹配值。然後再去最小值:min()這樣結果就為4。
但是以上上圖中的這個序列3,6,8用子查詢得出的結果也應該為4,而正確答案為1,顯然只是用子查詢這樣的方式處理是不完整的。
那為什麼要把1單獨判斷呢?這是由1的位置的特殊性決定的。因為1開始時總是處在序列的最前端的位置(正常情況下)。它的前面已經沒有數字了,也就是說不存在a.id+1=1(因為我們預設序列是從1開始增長的)。因此沒有哪個數字存在與否能判斷出1是否存在。所以1需要單獨考慮。
處於同樣的原理,我們可以用這種方式重用被刪除的鍵:
只要在前面加上:insert into ti_test(id,val) select .....(同上)即可。
當然你可以使用coalesce函式來合併,存在1和不存在1的情況:
如下:select coalesce(min(a.id+1),1)
from tb_test a
where not exists (
select 1
from tb_test as b
where b.id=a.id+1
) and exists(select 1 from tb_test where id=1)
注:coalesce函式用於返回第乙個非空值。也就是說如果序列中沒有1,在被where篩選器篩選後,返回的值為null,此時min(a.id+1)也為null,這樣返回的結果就為1。
最後,並不推薦重用返回值並且在多執行緒執行時也可能得到重複的鍵。
原文發布時間為:2011-03-20
sql查詢最小缺失值與重用被刪除的鍵
在資料處理時,我們經常會使用一些 自增 的插入方式來處理資料。比如學生學號 b07051001,b07051002.類似的遞增關係的資料。但是,如果中途因為某些原因將其中的一些記錄刪除掉之後,就會出現斷續的記錄。這時,我們可能期待將這些中間的缺失值再次利用。以下,就談談如何查詢最小缺失值。首先,我們...
sql查詢最小缺失值與重用被刪除的鍵
在資料處理時,我們經常會使用一些 自增 的插入方式來處理資料。比如學生學號 b07051001,b07051002.類似的遞增關係的資料。但是,如果中途因為某些原因將其中的一些記錄刪除掉之後,就會出現斷續的記錄。這時,我們可能期待將這些中間的缺失值再次利用。以下,就談談如何查詢最小缺失值。首先,我們...
分組查詢最大 最小值sql
經典題目 查詢每個班級的最高分,查詢每種日誌的最晚記錄 1.查詢每個班級的最高分 不考慮同一分數的 思路 首先利用max group by取出每組最高的分數,再與表自連線 sql語句 select t1.id,t1.name,t1.calssid,t2.score from t zhb t1 sel...