Поиск повторяющихся данных в Oracle - PullRequest
1 голос
/ 14 октября 2011

У меня есть таблица с 500 000+ записями и полями для ID, имени, фамилии и адреса электронной почты.Я пытаюсь найти строки, в которых имя и фамилия являются дубликатами (поскольку у одного и того же человека есть два отдельных идентификатора, адреса электронной почты или что-то еще, они находятся в таблице более одного раза).Я думаю, что знаю, как найти дубликаты с помощью GROUP BY, вот что у меня есть:

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

Проблема в том, что мне нужно затем переместить всю строку с этими дублированными именами в другую таблицу.Есть ли способ найти дубликаты и получить всю строку?Или хотя бы получить удостоверения личности?Я попытался использовать самосоединение, но вернул больше строк, чем было в таблице для начала.Это был бы лучший подход?Любая помощь будет принята с благодарностью.

Ответы [ 4 ]

3 голосов
/ 14 октября 2011

Наиболее эффективный способ удаления повторяющихся строк - это самостоятельное соединение:

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);
2 голосов
/ 14 октября 2011

Индекс на (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
      )
1 голос
/ 16 октября 2011

Чтобы добавить другую опцию, я обычно использую эту для удаления дубликатов:

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 )
1 голос
/ 14 октября 2011

Это даст вам идентификатор, который вы хотите переместить / удалить / и т.д.Обратите внимание, что он не работает, если count (*)> 2, поскольку вы получаете только 1 идентификатор (вы можете повторно выполнить запрос для этих случаев).

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

Редактировать: Вы можете использовать COLLECT , чтобы получить все идентификаторы одновременно (но будьте осторожны, поскольку вы хотите переместить / удалить только все , кроме одного )

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...