在Oracle中查找重复数据

时间:2011-10-14 17:52:22

标签: database oracle duplicates oracle11g

我有一张包含500,000多条记录的表格,以及ID,名字,姓氏和电子邮件地址的字段。我要做的是找到名字和姓氏都是重复的行(因为同一个人有两个独立的ID,电子邮件地址,或者其他什么,他们不止一次在表中)。我想我知道如何使用GROUP BY找到重复项,这就是我所拥有的:

SELECT first_name, last_name, COUNT(*)
FROM person_table
GROUP BY first_name, last_name
HAVING COUNT(*) > 1

问题是我需要将整个行与这些重复的名称一起移动到另一个表中。有没有办法找到重复项并获得整行?或者至少获得ID?我尝试使用自联接,但是开始时返回的行数多于表中的行数。这会是一个更好的方法吗?任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:3)

删除重复行的最有效方法是使用自联接:

DELETE FROM person_table a
 WHERE a.rowid > 
       ANY (SELECT b.rowid
              FROM person_table b
             WHERE a.first_name = b.first_name
               AND a.last_name  = b.last_name);

即使存在多个重复行,也会删除所有重复项。

此处有更多关于删除重复项和不同方法的内容:http://www.dba-oracle.com/t_delete_duplicate_table_rows.htm

希望它有所帮助...

编辑:根据您的评论,如果您想要选择除重复之外的所有副本,那么

SELECT *
  FROM person_table a
 WHERE a.rowid > 
       ANY (SELECT b.rowid
              FROM person_table b
             WHERE a.first_name = b.first_name
               AND a.last_name  = b.last_name);

答案 1 :(得分:2)

(first_name, last_name)(last_name, first_name)上的索引会有所帮助:

SELECT t.*
FROM 
    person_table t
  JOIN      
      ( SELECT first_name, last_name
        FROM person_table
        GROUP BY first_name, last_name
        HAVING COUNT(*) > 1
      ) dup
    ON  dup.last_name = t.last_name
    AND dup.first_name = t.first_name

或:

SELECT t.*
FROM person_table t
WHERE EXISTS
      ( SELECT *
        FROM person_table dup
        WHERE dup.last_name = t.last_name
          AND dup.first_name = t.first_name
          AND dup.ID <> t.ID
      )

答案 2 :(得分:1)

这将为您提供要移动/删除/等的ID。请注意,如果count(*)&gt;它不起作用2,因为您只获得1个ID(您可以针对这些情况重新运行查询)。

SELECT max(ID), first_name, last_name, COUNT(*)
FROM person_table
GROUP BY first_name, last_name
HAVING COUNT(*) > 1

修改:您可以使用COLLECT一次获取所有ID(但要小心,因为您只想移动/删除所有但只有一个

答案 3 :(得分:1)

要添加其他选项,我通常会使用此选项删除重复项:

delete from person_table
where rowid in (select rid
                  from (select rowid rid, row_number() over
                         (partition by first_name,last_name order by rowid) rn
                          from person_table
                        )
                 where rn <> 1 )