Поиск повторяющихся значений в MySQL

У меня есть таблица со столбцом типа varchar, и я хотел бы найти все записи, которые имеют одинаковые значения в этом столбце. Какой лучший запрос я могу использовать для поиска дубликатов?

21 ответов


сделать SELECT С GROUP BY предложения. Скажем имя это столбец, в котором вы хотите найти дубликаты:

SELECT name, COUNT(*) c FROM table GROUP BY name HAVING c > 1;

это вернет результат с имя значение в первом столбце, и сколько раз это значение отображается во втором.


SELECT varchar_col
FROM table
GROUP BY varchar_col
HAVING count(*) > 1;

SELECT  *
FROM    mytable mto
WHERE   EXISTS
        (
        SELECT  1
        FROM    mytable mti
        WHERE   mti.varchar_column = mto.varchar_column
        LIMIT 1, 1
        )

этот запрос возвращает все записи, а не только отдельных varchar_column ' s.

этот запрос не использует COUNT(*). Если есть много дубликатов, COUNT(*) дорого, и вам не нужно все COUNT(*), вам просто нужно знать, если есть две строки с одинаковым значением.

имея индекс на varchar_column, конечно, значительно ускорит этот запрос.


построение ответа Левика, чтобы получить идентификаторы повторяющихся строк, которые вы можете сделать GROUP_CONCAT если ваш сервер поддерживает его (это вернет список идентификаторов, разделенных запятыми).

SELECT GROUP_CONCAT(id), name, COUNT(*) c FROM documents GROUP BY name HAVING c > 1;

SELECT * 
FROM `dps` 
WHERE pid IN (SELECT pid FROM `dps` GROUP BY pid HAVING COUNT(pid)>1)

предполагая, что ваша таблица называется TableABC, а столбец, который вы хотите, - Col, а первичный ключ к T1-ключ.

SELECT a.Key, b.Key, a.Col 
FROM TableABC a, TableABC b
WHERE a.Col = b.Col 
AND a.Key <> b.Key

преимущество этого подхода над приведенным выше ответом заключается в том, что он дает ключ.


чтобы узнать, сколько записей дублируется в столбце имя в Employee, следующий запрос полезен;

Select name from employee group by name having count(*)>1;

SELECT t.*,(select count(*) from city as tt
  where tt.name=t.name) as count
  FROM `city` as t
  where (
     select count(*) from city as tt
     where tt.name=t.name
  ) > 1 order by count desc

заменить города С вашего стола. Заменить имя С вашим именем Поля


мой последний запрос включил несколько ответов здесь, которые помогли-объединение group by, count & GROUP_CONCAT.

SELECT GROUP_CONCAT(id), `magento_simple`, COUNT(*) c 
FROM product_variant 
GROUP BY `magento_simple` HAVING c > 1;

Это предоставляет идентификатор обоих примеров (разделенных запятыми), штрих-код, который мне нужен, и сколько дубликатов.

изменить таблицу и столбцы соответственно.


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

но если вам нужно проверить больше столбцов и хотите проверить комбинацию результата, чтобы этот запрос работал нормально:

SELECT COUNT(CONCAT(name,email)) AS tot,
       name,
       email
FROM users
GROUP BY CONCAT(name,email)
HAVING tot>1 (This query will SHOW the USER list which ARE greater THAN 1
              AND also COUNT)

SELECT 
    t.*,
    (SELECT COUNT(*) FROM city AS tt WHERE tt.name=t.name) AS count 
FROM `city` AS t 
WHERE 
    (SELECT count(*) FROM city AS tt WHERE tt.name=t.name) > 1 ORDER BY count DESC

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

SELECT product_id FROM oc_product_reward GROUP BY product_id HAVING count( product_id ) >1

код взят из: http://chandreshrana.blogspot.in/2014/12/find-duplicate-records-based-on-any.html


CREATE TABLE tbl_master
    (`id` int, `email` varchar(15));

INSERT INTO tbl_master
    (`id`, `email`) VALUES
    (1, 'test1@gmail.com'),
    (2, 'test2@gmail.com'),
    (3, 'test1@gmail.com'),
    (4, 'test2@gmail.com'),
    (5, 'test5@gmail.com');

QUERY : SELECT id, email FROM tbl_master
WHERE email IN (SELECT email FROM tbl_master GROUP BY email HAVING COUNT(id) > 1)

С @maxyfc это ответ далее мне нужно было найти все строк, которые были возвращены с повторяющимися значениями, поэтому я мог редактировать их в MySQL Workbench:

SELECT * FROM table
   WHERE field IN (
     SELECT field FROM table GROUP BY field HAVING count(*) > 1
   ) ORDER BY field

Я не вижу никаких присоединений, whitch имеет много применений с точки зрения дубликатов.

Это aproeach дает вам фактические удвоенные результаты.

SELECT t1.* FROM table as t1 LEFT JOIN table as t2 ON t1.name=t2.name and t1.id!=t2.id WHERE t2.id IS NOT NULL ORDER BY t1.name

SELECT DISTINCT a.email FROM `users` a LEFT JOIN `users` b ON a.email = b.email WHERE a.id != b.id;

для удаления повторяющихся строк с несколькими полями сначала отмените их на новый уникальный ключ, который указан только для отдельных строк, затем используйте команду "group by" для удаления повторяющихся строк с тем же новым уникальным ключом:

Create TEMPORARY table tmp select concat(f1,f2) as cfs,t1.* from mytable as t1;
Create index x_tmp_cfs on tmp(cfs);
Create table unduptable select f1,f2,... from tmp group by cfs;

один очень поздний вклад... в случае, если это поможет кому-нибудь waaaaaay вниз по линии... У меня была задача найти совпадающие пары транзакций (фактически обе стороны переводов со счета на счет) в банковском приложении, чтобы определить, какие из них были " от " и " до " для каждой транзакции между счетами, поэтому мы закончили с этим:

SELECT 
    LEAST(primaryid, secondaryid) AS transactionid1,
    GREATEST(primaryid, secondaryid) AS transactionid2
FROM (
    SELECT table1.transactionid AS primaryid, 
        table2.transactionid AS secondaryid
    FROM financial_transactions table1
    INNER JOIN financial_transactions table2 
    ON table1.accountid = table2.accountid
    AND table1.transactionid <> table2.transactionid 
    AND table1.transactiondate = table2.transactiondate
    AND table1.sourceref = table2.destinationref
    AND table1.amount = (0 - table2.amount)
) AS DuplicateResultsTable
GROUP BY transactionid1
ORDER BY transactionid1;

в результате DuplicateResultsTable предоставляет строки, содержащие совпадающие (т. е. повторяющиеся) транзакции, но также предоставляет ту же транзакцию id в обратном порядке во второй раз он соответствует той же паре, поэтому внешний SELECT можно ли группировать по первому идентификатору транзакции, что делается с помощью LEAST и GREATEST чтобы убедиться, что два transactionid всегда находятся в одном порядке в результатах, что делает его безопасным для GROUP первым, тем самым устраняя все дубликаты совпадений. Пробежал почти миллион записей и идентифицировал 12,000+ матчей всего за 2 секунды. Конечно, transactionid является основным индексом, который действительно помогать.


Select column_name, column_name1,column_name2, count(1) as temp from table_name group by column_name having temp > 1

SELECT ColumnA, COUNT( * )
FROM Table
GROUP BY ColumnA
HAVING COUNT( * ) > 1

Я предпочитаю использовать оконные функции (MySQL 8.0+) для поиска дубликатов, потому что я мог видеть всю строку:

WITH cte AS (
  SELECT *
    ,COUNT(*) OVER(PARTITION BY col_name) AS num_of_duplicates_group
    ,ROW_NUMBER() OVER(PARTITION BY col_name ORDER BY col_name2) AS pos_in_group
  FROM table
)
SELECT *
FROM cte
WHERE num_of_duplicates_group > 1;

DB Fiddle Demo