删除表中重复记录

 

删除表中重复记录

LazyBee

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

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

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

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

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

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

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

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

以下是相应的 sql 语句块:
 1 Begin   Tran  LazyBee
 2 declare   @tmp   Table
 3 (lLIstHeader_id  int ,lEncounter_id  int ,dtLastUpdate_dt  datetime ,
 4  sLastUpdate_id  char ( 10 ),iConcurrency_id  int )
 5
 6 Insert   @tmp (lLIstHeader_id,lEncounter_id,dtLastUpdate_dt,sLastUpdate_id,iConcurrency_id)
 7 select  lListHeader_id,lEncounter_id,dtLastUpdate_dt,sLastUpdate_id,iConcurrency_id  
 8 from  lstHeaderencounter
 9   group   by  lListHeader_id,lEncounter_id,dtLastUpdate_dt,sLastUpdate_id,iConcurrency_id 
10 having   count ( * ) > 1  
11
12 delete  lstHeaderencounter  from   @tmp  d 
13 where  d.lListHeader_id = lstHeaderencounter.lListHeader_id  and  
14       d.lEncounter_id = lstHeaderencounter.lEncounter_id
15
16 insert  lstHeaderencounter(lLIstHeader_id,lEncounter_id,dtLastUpdate_dt,sLastUpdate_id,iConcurrency_id)
17 select  lListHeader_id,lEncounter_id,dtLastUpdate_dt,sLastUpdate_id,iConcurrency_id 
18   from   @tmp
19
20 if   @@error <> 0
21 Begin
22       print   ' roll back '
23       RollBack   Tran  LazyBee
24    End
25 else
26 Begin
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 , 1 as  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 直接删除:
 1 Delete  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_id lOrder_num 最大值的记录(注:这里假设表中不存在两条完全相同的记录,如果存在的话只能通过前面的方法来进行删除)。

转载于:https://www.cnblogs.com/LazyBee/archive/2008/06/05/1214102.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值