我有一张包含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?我尝试使用自联接,但是开始时返回的行数多于表中的行数。这会是一个更好的方法吗?任何帮助将不胜感激。
答案 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 )