Найти дубликаты записей в MySQL - PullRequest
613 голосов
/ 12 мая 2009

Я хочу вытащить дубликаты записей в базе данных MySQL. Это можно сделать с помощью:

SELECT address, count(id) as cnt FROM list
GROUP BY address HAVING cnt > 1

Что приводит к:

100 MAIN ST    2

Я хотел бы вытащить его, чтобы он показывал каждую строку, которая является дубликатом. Что-то вроде:

JIM    JONES    100 MAIN ST
JOHN   SMITH    100 MAIN ST

Есть мысли о том, как это можно сделать? Я стараюсь не делать первый, а затем искать дубликаты со вторым запросом в коде.

Ответы [ 22 ]

649 голосов
/ 12 мая 2009

Ключ заключается в том, чтобы переписать этот запрос, чтобы его можно было использовать в качестве подзапроса.

SELECT firstname, 
   lastname, 
   list.address 
FROM list
   INNER JOIN (SELECT address
               FROM   list
               GROUP  BY address
               HAVING COUNT(id) > 1) dup
           ON list.address = dup.address;
337 голосов
/ 19 марта 2012
SELECT date FROM logs group by date having count(*) >= 2
193 голосов
/ 12 мая 2009

Почему бы просто НЕ ВНУТРИ СОЕДИНИТЬСЯ за столом с самим собой?

SELECT a.firstname, a.lastname, a.address
FROM list a
INNER JOIN list b ON a.address = b.address
WHERE a.id <> b.id

DISTINCT необходим, если адрес может существовать более двух раз.

53 голосов
/ 08 января 2014

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

SELECT COUNT(*) c,title FROM `data` GROUP BY title HAVING c > 1;
42 голосов
/ 20 июня 2011
select `cityname` from `codcities` group by `cityname` having count(*)>=2

Это тот же запрос, который вы просили, и он на 200% работает и легко. Наслаждайтесь !!! * * 1002

35 голосов
/ 26 января 2012

Поиск дублированных пользователей по адресу электронной почты с этим запросом ...

SELECT users.name, users.uid, users.mail, from_unixtime(created)
FROM users
INNER JOIN (
  SELECT mail
  FROM users
  GROUP BY mail
  HAVING count(mail) > 1
) dupes ON users.mail = dupes.mail
ORDER BY users.mail;
21 голосов
/ 01 марта 2018

Не проще ли:

SELECT *
FROM tc_tariff_groups
GROUP BY group_id
HAVING COUNT(group_id) >1

19 голосов
/ 02 марта 2013

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

SELECT COUNT(*), column1, column2 
FROM tablename
GROUP BY column1, column2
HAVING COUNT(*)>1;
13 голосов
/ 14 июня 2012

Другое решение - использовать псевдонимы таблиц, например:

SELECT p1.id, p2.id, p1.address
FROM list AS p1, list AS p2
WHERE p1.address = p2.address
AND p1.id != p2.id

Все, что вы действительно делаете в этом случае, - это взятие исходной таблицы list , создание двух p таблиц повторного участия - p 1 и p 2 - из этого и затем выполняется соединение по столбцу адреса (строка 3). Четвертая строка гарантирует, что одна и та же запись не будет отображаться несколько раз в наборе результатов («дубликаты дубликатов»).

11 голосов
/ 26 января 2012

Поиск дубликатов адресов гораздо сложнее, чем кажется, особенно если вам требуется точность. В этом случае недостаточно запроса MySQL ...

Я работаю на SmartyStreets , где мы занимаемся проверкой правильности и дедупликации и другими вещами, и я видел множество разнообразных проблем с похожими проблемами.

Существует несколько сторонних сервисов, которые помечают дубликаты в списке для вас. Выполнение этого только с подзапросом MySQL не будет учитывать различия в форматах и ​​стандартах адресов. У USPS (для адреса в США) есть определенные руководящие принципы, чтобы сделать эти стандарты, но только небольшая часть поставщиков сертифицирована для выполнения таких операций.

Итак, я бы порекомендовал вам лучший ответ - экспортировать таблицу, например, в CSV-файл и отправить ее в работающий обработчик списков. Один из них - LiveAddress , который автоматически сделает это за вас от нескольких секунд до нескольких минут. Он будет отмечать повторяющиеся строки с новым полем с именем «Duplicate» и значением Y.

...