• 删除表中重复记录


     

    删除表中重复记录

    LazyBee

    最近由于要给旧系统的表中增加主键(SQL Server2000的表),由于旧表中存在重复记录所以导致增加不上,所以需要写一段SQL语句来删除所有的重复记录(就是必须保留重复记录中的一条,维持数据记录的唯一性),我知道园子里大虾多,所以在这里集思广益,看看大家都有什么好的办法:

    方法一:
         1
    为了保证完整性,首先启动一个事务

    2 声明一个表变量(在这里使用表变量主要是考虑重复的数据不是很多,同时为了获得更好的性能;当然如果重复的数据特别多,使用临时表是更

    好的选择,因为表变量的数据都是存在内存中的,如果数据量大,可能导致内存吃紧。)用于存储重复性的数据,这个需要定义成和源表一样。

           3 将重复记录的一条插入到表变量中。

           4 删除所有有重复记录的记录

           5 将表变量中的记录插入的源表中。

           6 如果出错,回滚事务,否则提交事务

    以下是相应的sql语句块:
     1Begin Tran LazyBee
     2declare @tmp Table
     3(lLIstHeader_id int,lEncounter_id int,dtLastUpdate_dt datetime,
     4 sLastUpdate_id char(10),iConcurrency_id int)
     5
     6Insert @tmp(lLIstHeader_id,lEncounter_id,dtLastUpdate_dt,sLastUpdate_id,iConcurrency_id)
     7select lListHeader_id,lEncounter_id,dtLastUpdate_dt,sLastUpdate_id,iConcurrency_id  
     8from lstHeaderencounter
     9 group by lListHeader_id,lEncounter_id,dtLastUpdate_dt,sLastUpdate_id,iConcurrency_id 
    10having count(*)>1 
    11
    12delete lstHeaderencounter from @tmp d 
    13where d.lListHeader_id=lstHeaderencounter.lListHeader_id and 
    14      d.lEncounter_id=lstHeaderencounter.lEncounter_id
    15
    16insert lstHeaderencounter(lLIstHeader_id,lEncounter_id,dtLastUpdate_dt,sLastUpdate_id,iConcurrency_id)
    17select lListHeader_id,lEncounter_id,dtLastUpdate_dt,sLastUpdate_id,iConcurrency_id 
    18 from @tmp
    19
    20if @@error<>0
    21Begin
    22     print 'roll back'
    23     RollBack Tran LazyBee
    24  End
    25else
    26Begin
    27   print 'Success'
    28     Commit Tran LazyBee
    29  End
    30

    我知道这个方法不够通用,因为如果有多个类似重复记录的表存在,将每次都要修改表定义和插入语句的字段内容,不知各位有没有好的方法或意见,大家讨论讨论:) 
     

    刚在网上找到另外一些解决方案,感觉也挺不错的

    方法二:

           1 创建一个临时表,这个临时表的结构和源表一样

           2 给这个临时表增加一个唯一索引(根据需要),并且选中忽略重复值

           3 将源表的记录全部插入临时表中,这时会因为重复记录出现3604的错误。

           4 删除源表的记录,将临时表的记录插入源表中,然后删除临时表。

    方法三(主要针对重复记录完全相同的情况):

           1 利用distinct将唯一记录插入临时表中

                    2 然后将唯一记录再倒回源表中
     
    Select distinct * into #Tmp from tableName
    Drop table tableName
    Select * into tableName from #Tmp
    Drop table #Tmp
      

    方法四(主要针对记录部分字段相同的记录):

           这种方法和方法一有点类似,不过实现方法不同而已。在这里使用了两个临时表.我们假设重复字段为lListHeader_id,lEncounter_id,要求得到这两

    个字段的唯一结果集,我们保留重复记录的第一条,当然如果保留重复记录的最后一条可以使用max代替min
          
    Select identity(int,1,1as autoID, * into #Tmp from tableName
    Select min(autoID) as autoID into #Tmp2 from #Tmp group by lListHeader_id,lEncounter_id
    Select * from #Tmp where autoID in (Select autoID from #Tmp2)
     

    方法五(也是针对部分字段相同的记录)

           SQL直接删除:
     1Delete lstStructureItems from  
     2        (select lStructure_id,lListHeader_id,lList_id,max(lParent_id) as lParent_id,max(lOrder_num) as lOrder_num,lDoctor_id 
     3         from lstStructureItems 
     4         group by lStructure_id,lListHeader_id,lList_id,lDoctor_id
     5         having count(*)>1) d 
     6 where
     7 lstStructureItems.lStructure_id=d.lStructure_id and
     8 lstStructureItems.lListHeader_id=d.lListHeader_id and
     9 lstStructureItems.lList_id=d.lList_id and
    10 lstStructureItems.lDoctor_id=d.lDoctor_id and
    11 (lstStructureItems.lParent_id<>d.lParent_id or
    12 lstStructureItems.lOrder_num<>d.lOrder_num)
    13
    在这里我们为了给lStructure_id,lListHeader_id,lList_id,lDoctor_id四个字段增加一个唯一索引,所以需要只保留这四个字段保持唯一的值,其他的都需要删除。所以我们采用将这四个字段进行group by,然后保留lParent_idlOrder_num最大值的记录(注:这里假设表中不存在两条完全相同的记录,如果存在的话只能通过前面的方法来进行删除)。
  • 相关阅读:
    笔记:Linux进程间通信机制
    Linux下C/C++和lua交互-Table
    @JsonFormat时间格式化注解使用
    关于 mybatis 报invalid comparison: java.util.Arrays$ArrayList and java.lang.String异常
    @RestControllerAdvice作用及原理
    MySQL 中 datetime 和 timestamp 的区别与选择
    idea提交svn忽略.class等文件的相关配置(so easy)
    PLSQL Developer建表时注释(COMMENT)中文乱码的解决方案(Windows)
    oracle客户端安装与配置
    PLSQL安装、PLSQL汉化、激活
  • 原文地址:https://www.cnblogs.com/LazyBee/p/1214102.html
Copyright © 2020-2023  润新知