做项目的时候一位同事导数据的时候不小心把一个表中的数据全都搞重了也就是说这个表里所有的记录都有一条重复的这个表的数据是千万级的而且是生产系统也就是说不能把所有的记录都删除而且必须快速的把重复记录删掉对此总结了一下删除重复记录的方法以及每种方法的优缺点
为了陈诉方便假设表名为Tbl表中有三列colcolcol其中colcol是主键并且colcol上加了索引
通过创建临时表
可以把数据先导入到一个临时表中然后删除原表的数据再把数据导回原表SQL语句如下
creat table tbl_tmp (select distinct* from tbl);truncate table tbl;//清空表记录
insert into tbl select * from tbl_tmp;//将临时表中的数据插回来
这种方法可以实现需求但是很明显对于一个千万级记录的表这种方法很慢在生产系统中这会给系统带来很大的开销不可行
利用rowid
在oracle中每一条记录都有一个rowidrowid在整个数据库中是唯一的rowid确定了每条记录是oracle中的哪一个数据文件块行上在重复的记录中可能所有列的内容都相同但rowid不会相同SQL语句如下
delete from tbl where rowid in (select arowid from tbl a tbl b where arowid>browid and l=l and l = l)
如果已经知道每条记录只有一条重复的这个sql语句适用但是如果每条记录的重复记录有N条这个N是未知的就要考虑适用下面这种方法了
利用max或min函数
这里也要使用rowid与上面不同的是结合max或min函数来实现SQL语句如下
delete from tbl awhere rowid not in (select max(browid)
from tbl b where l=l and l = l);//这里max使用min也可以
或者用下面的语句
delete from tbl awhere rowid<(select max(browid) from tbl b where l=l and l = l);
//这里如果把max换成min的话前面的where子句中需要把<改为>
跟上面的方法思路基本是一样的不过使用了group by减少了显性的比较条件提高效率SQL语句如下
deletefrom tbl where rowid not in (select max(rowid) from tbl tgroup by l l);
delete from tbl where (col col) in (select colcol from tblgroup bycolcolhavingcount(*) >)
and rowidnotin(selectnin(rowid)fromtblgroup bycolcolhavingcount(*) >)
还有一种方法对于表中有重复记录的记录比较少的并且有索引的情况比较适用假定colcol上有索引并且tbl表中有重复记录的记录比较少SQL语句如下利用group by提高效率
Group By方法(我经常所用的一种方法)
一查数据
Select count(Num) max(Name) from student 列出重复记录并列出属性
Group By Name
Having count(Num) > 按Name分组后找出表中Num列重复即出现次数大于
二删数据
Delete from student Group By Name Having count(Num) >