51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 6698|回复: 4
打印 上一主题 下一主题

Oracle数据库删除重复记录的方法

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2008-12-24 18:39:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
做项目的时候,一位同事导数据的时候,不小心把一个表中的数据全都搞重了,也就是说,这个表里所有的记录都有一条重复的。这个表的数据是千万级的,而且是生产系统。也就是说,不能把所有的记录都删除,而且必须快速的把重复记录删掉。对此,总结了一下删除重复记录的方法,以及每种方法的优缺点。
   为了陈诉方便,假设表名为Tbl,表中有三列col1,col2,col3,其中col1,col2是主键,并且,col1,col2上加了索引。
1、通过创建临时表
    可以把数据先导入到一个临时表中,然后删除原表的数据,再把数据导回原表,SQL语句如下:


creat table tbl_tmp (select distinct* from tbl);
truncate table tbl;//清空表记录
insert into tbl select * from tbl_tmp;//将临时表中的数据插回来。
    这种方法可以实现需求,但是很明显,对于一个千万级记录的表,这种方法很慢,在生产系统中,这会给系统带来很大的开销,不可行。
2、利用rowid
    在oracle中,每一条记录都有一个rowid,rowid在整个数据库中是唯一的,rowid确定了每条记录是oracle中的哪一个数据文件、块、行上。在重复的记录中,可能所有列的内容都相同,但rowid不会相同。SQL语句如下:
delete from tbl where rowid in (
select a.rowid from tbl a, tbl b where a.rowid>b.rowid and a.col1=b.col1 and a.col2 = b.col2)
    如果已经知道每条记录只有一条重复的,这个sql语句适用。但是如果每条记录的重复记录有N条,这个N是未知的,就要考虑适用下面这种方法了。
3、利用max或min函数
这里也要使用rowid,与上面不同的是结合max或min函数来实现。SQL语句如下
delete from tbl awhere rowid not in (
select max(b.rowid)
from tbl b where a.col1=b.col1 and a.col2 = b.col2);//这里max使用min也可以
或者用下面的语句
delete from tbl awhere rowid<(select max(b.rowid)
from tbl b where a.col1=b.col1 and a.col2 = b.col2);
//这里如果把max换成min的话,前面的where子句中需要把"<"改为">"
跟上面的方法思路基本是一样的,不过使用了group by,减少了显性的比较条件,提高效率。SQL语句如下:
deletefrom tbl where rowid not in (select max(rowid)
from tbl tgroup by t.col1, t.col2);
delete from tbl where (col1, col2) in (select col1,col2 from tblgroup bycol1,col2havingcount(*) >1)
and rowidnotin(selectnin(rowid)fromtblgroup bycol1,col2havingcount(*) >1)
   还有一种方法,对于表中有重复记录的记录比较少的,并且有索引的情况,比较适用。假定col1,col2上有索引,并且tbl表中有重复记录的记录比较少,SQL语句如下4、利用group by,提高效率
4、Group By方法(我经常所用的一种方法)
一、查数据
    Select count(Num) ,max(Name) from student   --列出重复记录,并列出属性
    Group By Name
    Having count(Num) >1    --按Name分组后找出表中Num列重复,即出现次数大于1

二、删数据
    Delete from student Group By Name Having count(Num) > 1
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

该用户从未签到

2#
发表于 2008-12-30 16:48:11 | 只看该作者
如果有主键索引的话,是不会有重复记录的,不知道阁下是怎么做到得。
回复 支持 反对

使用道具 举报

  • TA的每日心情
    开心
    2016-12-19 17:15
  • 签到天数: 6 天

    连续签到: 1 天

    [LV.2]测试排长

    3#
    发表于 2009-11-21 11:56:44 | 只看该作者

    谢谢分享
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2022-5-8 19:23
  • 签到天数: 137 天

    连续签到: 1 天

    [LV.7]测试师长

    4#
    发表于 2010-4-24 22:11:09 | 只看该作者
    没有做唯一索引吧,所以会有重复记录

    不知道楼主最后选用了哪种方式去处理重复数据,哪种的效率最高
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    5#
    发表于 2014-1-16 11:20:26 | 只看该作者
    感觉楼主的的count&#40;*)&#62;1,应该加个"&#61;"号吧?
    不然,会把没重复的数据都删了。


    我的表Ly简单如上,我用的&#83;QL是
    delete from Ly where rowid not in &#40;
    select max&#40;a.rowid) from Ly a group by a.nid having count&#40;a.nid)&#62;&#61;1
    );

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-25 04:30 , Processed in 0.075241 second(s), 28 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表