sql查找最小缺失值与重用被删除的键

在数据处理时,我们经常会使用一些“自增”的插入方式来处理数据。比如学生学号: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

本文作者:vinoYang

时间: 2024-08-30 12:21:00

sql查找最小缺失值与重用被删除的键的相关文章

sql server删除外键约束

  x先找出约束名字 然后删除它 我给个例子 --测试环境 --主表 create table test1(id int primary key not null,value int) insert test1 select 1,2 go --从表 create table test2(id int references test1(id),value int) go --第一步:找出test2表上的外键约束名字 --2000 exec sp_helpconstraint 'test2' --可

android-新手求助:安卓sql查找的函数,报错Nullpointerexception

问题描述 新手求助:安卓sql查找的函数,报错Nullpointerexception 代码如下 public User search(String username){ SQLiteDatabase sdb = helper.getReadableDatabase(); Cursor cursor =sdb.rawQuery("select * from user where username=?", new String[]{username}); if(cursor.moveTo

数据-C# sql 查找每个分库中某表某ID字段重复的记录

问题描述 C# sql 查找每个分库中某表某ID字段重复的记录 目前30个分库中,每个库目前至少有100万条记录,每个库同有一个数据表A,表结构相同.每个表的主键叫recordID,但是各个分库间会重复不唯一.需求一个思路.忽略数据表设计问题,目前就是做出这个工具而已,表设计问题不管. 目前我是利用Sorteddiction的contains方法判断重复,但是会出现内存溢出的问题.OutOfMemory 解决方案 建临时表,先把所有表的recordID集中起来,然后再判断重复.

点击网页提示 404 - 找不到文件或目录。 您要查找的资源可能已被删除,已更改名称

问题描述 情况是这样的,网站的文章本来能正常显示的但是我们更改了下栏目位置就显示"点击网页提示404-找不到文件或目录.您要查找的资源可能已被删除,已更改名称",网站后台是集pc和手机一体的,手机端能显示但是PC端不能正常显示.还有个问题是:"在网站后台能直接点击编辑好的标题进入页面" 解决方案 解决方案二:404就是链接指向没找到文件.你手机能看可能是缓存.现在要做的就是仔细看下相对路径的问题.解决方案三:你好能加我qq远程帮我看看么解决方案四:求大神加QQ帮我看

SQL查找某一条记录的方法_MsSql

SQL查找第n条记录的方法: select top 1 * from table where id not in (select top n-1 id from table) temptable0 SQL查找第n条开始的m条记录的方法: select top m * from table where id not in (select top n-1 id from table) temptable0) (注:表中必须有一个唯一值字段才可适用此方法.) 

mysql sql enum数据类型插入,更新,删除操作

mysql教程 sql enum数据类型插入,更新,删除操作 enum列总有1个默认值.如果未指定默认值,对于包含null的列,默认值为null:否则,第1个枚举值将被当作默认值. 如果在enum列中插入了不正确的值,或者,如果使用ignore将值强制插入了enum列,会将其设置为保留的枚举值0,对于字符串情形,将显示为空字符串. 如果在set列中插入了不正确值,该值将被忽略.例如,如果列能包含值"a"."b"和"c",并赋值"a,x,

sql server ql语句删除外键和删除

sql server ql语句删除外键和删除 alter   table   tablename   add   constraint   ordersrelationship                           foreign   key   mployeeid       references   employees   (employeeid)                           on   delete     cascade                

SQL查找某一条记录的方法

SQL查找第n条记录的方法: select top 1 * from table where id not in (select top n-1 id from table) temptable0 SQL查找第n条开始的m条记录的方法: select top m * from table where id not in (select top n-1 id from table) temptable0) (注:表中必须有一个唯一值字段才可适用此方法.)

SQL Server上进行表设计时表的主键设计问题

关于数据库的逻辑设计,是一个很广泛的问题.本文主要针对开发应用中遇到在MS SQL Server上进行表设计时,对表的主键设计应注意的问题以及相应的解决办法. 主键设计现状和问题 关于数据库表的主键设计,一般而言,是根据业务需求情况,以业务逻辑为基础,形成主键. 比如,销售时要记录销售情况,一般需要两个表,一个是销售单的概要描述,记录诸如销售单号.总金额一类的情况,另外一个表记录每种商品的数量和金额.对于第一个表(主表),通常我们以单据号为主键;对于商品销售的明细表(从表),我们就需要将主表的单