Поиск повторяющихся значений в MySQL
У меня есть таблица со столбцом типа varchar, и я хотел бы найти все записи, которые имеют одинаковые значения в этом столбце. Какой лучший запрос я могу использовать для поиска дубликатов?
21 ответов
сделать SELECT
С GROUP BY
предложения. Скажем имя это столбец, в котором вы хотите найти дубликаты:
SELECT name, COUNT(*) c FROM table GROUP BY name HAVING c > 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;
предполагая, что ваша таблица называется 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
для удаления повторяющихся строк с несколькими полями сначала отмените их на новый уникальный ключ, который указан только для отдельных строк, затем используйте команду "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
Я предпочитаю использовать оконные функции (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;