• sql查找最小缺失值与重用被删除的键(转载)


    转载自:http://blog.csdn.net/yanghua_kobe/article/details/6262550

    在数据处理时,我们经常会使用一些“自增”的插入方式来处理数据。比如学生学号:B07051001,B07051002....类似的递增关系的数据。

    但是,如果中途因为某些原因将其中的一些记录删除掉之后,就会出现断续的记录。这时,我们可能期待将这些中间的缺失值再次利用。以下,就谈谈如何查找最小缺失值。

    首先,我们建一个测试表:tb_Test(主键并未设置为自增长):

    [c-sharp] view plain copy
     
     print?
    1. create table tb_Test  
    2. (  
    3.     id int primary key,  
    4.     val char(1) null  
    5. )  

    插入一些数据:

    [c-sharp] view plain copy
     
     print?
    1. insert into tb_Test values(1,'a')  
    2. insert into tb_Test values(2,'b')  
    3. insert into tb_Test values(3,'c')  
    4. insert into tb_Test values(4,'d')  
    5. insert into tb_Test values(5,'e')  
    6. insert into tb_Test values(6,'f')  
    7. insert into tb_Test values(7,'g')  
    8. 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。

    最后,并不推荐重用返回值并且在多线程运行时也可能得到重复的键。

  • 相关阅读:
    一个具体的例子学习Java volatile关键字
    JavaScript实现的水果忍者游戏,支持鼠标操作
    记录我开发工作中遇到HTTP跨域和OPTION请求的一个坑
    微信程序开发系列教程(四)使用微信API创建公众号自定义菜单
    微信程序开发系列教程(三)使用微信API给微信用户发文本消息
    Java实现 LeetCode 547 朋友圈(并查集?)
    Java实现 LeetCode 547 朋友圈(并查集?)
    Java实现 LeetCode 547 朋友圈(并查集?)
    Java实现 LeetCode 546 移除盒子(递归,vivo秋招)
    Java实现 LeetCode 546 移除盒子(递归,vivo秋招)
  • 原文地址:https://www.cnblogs.com/ismallboy/p/5855041.html
Copyright © 2020-2023  润新知