У меня есть таблица со столбцом varchar, и я хотел бы найти все записи, которые имеют повторяющиеся значения в этом столбце. Какой лучший запрос я могу использовать, чтобы найти дубликаты?
Но как это полезно, если вы не можете получить идентификаторы строк с повторяющимися значениями? Да, вы можете сделать новый запрос соответствия для каждого дублирующегося значения, но возможно ли просто перечислить дубликаты?
NobleUplift
23
@NobleUplift Вы можете сделать, GROUP_CONCAT(id)и он будет перечислять идентификаторы. Смотрите мой ответ для примера.
Мэтт Рардон
5
Что бы это значило, если бы сказали ERROR: column "c" does not exist LINE 1?
Пользователь
15
Я смущен, почему это принятый ответ и почему у него так много голосов. ОП спросил: «Я хотел бы найти в этом столбце все записи с одинаковыми значениями». Этот ответ возвращает таблицу отсчетов. -1
Моника Хедднек
4
Для тех, кто не понимает, как работает HAVING - это просто фильтр на наборе результатов, что происходит после основного запроса.
Джон Хант
236
SELECT varchar_col
FROMtableGROUPBY varchar_col
HAVING COUNT(*)>1;
Превосходит ответ @ levik, так как не добавляет лишний столбец. Делает это полезным для использования с IN()/ NOT IN().
Wmassingham
172
SELECT*FROM mytable mto
WHEREEXISTS(SELECT1FROM mytable mti
WHERE mti.varchar_column = mto.varchar_column
LIMIT 1,1)
Этот запрос возвращает полные записи, а не только отдельные varchar_column.
Этот запрос не использует COUNT(*). Если дубликатов много, они COUNT(*)дорогие и вам не нужно целое COUNT(*), вам просто нужно знать, есть ли две строки с одинаковым значением.
varchar_columnКонечно, наличие индекса значительно ускорит этот запрос.
Отлично. Я добавил ORDER BY varchar_column DESCв конец запроса.
Транте
8
Это должен быть принятый ответ, так как GROUP BYи HAVINGвозвращает только один из возможных дубликатов. Кроме того, производительность с индексированным полем вместо COUNT(*), и возможность ORDER BYгруппировать дубликаты записей.
Реми Бретон,
1
Как указано в комментариях выше, этот запрос позволяет вам перечислить все дублированные строки. Очень полезный.
TryHarder
4
Глядя на это, я не понимаю, как это будет работать вообще. Разве внутреннее условие всегда будет истинным, поскольку любая строка во внешней таблице будет также доступна во внутренней таблице, и поэтому каждая строка всегда будет хотя бы соответствовать самой себе? Я попробовал запрос и получил результат, который я подозревал - каждая строка вернулась. Но с таким большим количеством голосов я сомневаюсь в себе. Во внутреннем запросе отсутствует что-то вроде «AND mto.id <> mti.id»? Это работает для меня, когда я добавляю это.
Клок
2
@Quassnoi Хорошо. Я пытался поместить его в sqlfiddle, но я отказался, так как каждый запрос, который я пытаюсь выполнить, кроме создания схемы, получает тайм-аут. Я понял, что удаление «EXISTS» также делает запрос корректным для меня.
Клок
144
Составив ответ levik, чтобы получить идентификаторы дублирующихся строк, вы можете сделать это, GROUP_CONCATесли ваш сервер его поддерживает (это вернет список идентификаторов, разделенных запятыми).
SELECT GROUP_CONCAT(id), name, COUNT(*) c FROM documents GROUPBY name HAVING c >1;
Все это время, не зная о GROUP_CONCAT ()! очень очень полезно
августа
Действительно ценится Мэтт. Это действительно полезно! Для тех, кто пытается обновить в phpmyadmin, если вы оставляете идентификатор вместе с функцией, подобной этой: SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...]она включает встроенное редактирование и должна обновлять все задействованные строки (или, по крайней мере, первую совпадающую строку), но, к сожалению, редактирование генерирует ошибку Javascript. ..
Armfoot
Как бы вы тогда подсчитали, сколько идентификаторов подвержены дублированию?
CMCDragonkai
2
Как я не получаю все идентификаторы сгруппированы, но вместо этого перечислены от первого до последнего; со всеми соответствующими значениями в столбцах рядом с ними? Таким образом, вместо группировки, он просто показывает ID 1 и его значение, ID 2 и его значение. ДАЖЕ, если значения для идентификатора совпадают.
MailBlade
1
Чрезвычайно полезный ответ, это должно быть сверху, чтобы больше людей видели это. Я помню, сколько боли я пережил, создав такие списки, и это было доступно все время как команда ..
Джон
13
Предполагая, что ваша таблица называется TableABC, а столбец, который вам нужен, это Col, а первичный ключ к T1 - Key.
SELECT a.Key, b.Key, a.Col
FROM TableABC a, TableABC b
WHERE a.Col = b.Col
AND a.Key<> b.Key
Преимущество этого подхода перед приведенным выше ответом заключается в том, что он дает ключ.
+1 Потому что это удобно. Хотя, по иронии судьбы, сам результат содержит дубликаты (в нем перечислены a и b, затем b и a.)
Fabien Snauwaert
2
@FabienSnauwaert Вы можете избавиться от некоторых дубликатов, сравнив меньше (или больше чем)
Майкл
@TechTravelThink ваш ответ очень ясен, спасибо за это, но для большой таблицы это занимает некоторое время (около 2 млн. При более 20 000 таблицах записей), и после показа 25 первых результатов, если я нажму, чтобы показать следующий, phpmyadmin show error "# 1052 - «Идентификатор столбца в предложении заказа неоднозначен»
bcag2
12
SELECT*FROM`dps`WHERE pid IN(SELECT pid FROM`dps`GROUPBY pid HAVING COUNT(pid)>1)
Нет, потому что это, пожалуй, самый медленный из всех. Подвыборы известны своей медлительностью, поскольку они выполняются для каждой возвращаемой строки.
Оддман
10
Чтобы узнать, сколько записей являются дубликатами в столбце имени в Employee, полезен следующий запрос;
Select name from employee groupby name having count(*)>1;
К вашему сведению - вы захотите «выбрать отличный somecol ..», если существует вероятность существования более 1 дублированной записи, иначе результаты будут содержать дубликаты найденных дублированных строк.
Дрю
7
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
)>1orderby count desc
Замените город своей таблицей. Замените имя на имя вашего поля
Принимая @ maxyfc в ответ дальше, мне нужно , чтобы найти все из строк , которые были возвращены с повторяющимися значениями, так что я мог редактировать их в MySQL Workbench :
SELECT*FROMtableWHERE field IN(SELECT field FROMtableGROUPBY field HAVING count(*)>1)ORDERBY field
Я видел приведенный выше результат, и запрос будет работать нормально, если вам нужно проверить значение одного столбца, которые являются дубликатами. Например, электронная почта.
Но если вам нужно проверить больше столбцов и хотите проверить комбинацию результата, этот запрос будет работать нормально:
SELECT COUNT(CONCAT(name,email))AS tot,
name,
email
FROM users
GROUPBY CONCAT(name,email)HAVING tot>1(This query will SHOW the USER list which ARE greater THAN 1AND also COUNT)
Именно то, что было нужно! Вот мой запрос, проверяющий 3 поля на дубликаты:SELECT COUNT(CONCAT(userid,event,datetime)) AS total, userid, event, datetime FROM mytable GROUP BY CONCAT(userid, event, datetime ) HAVING total>1
Кай Ноак
4
Я предпочитаю использовать оконные функции (MySQL 8.0+) для поиска дубликатов, потому что я мог видеть всю строку:
WITH cte AS(SELECT*,COUNT(*)OVER(PARTITIONBY col_name)AS num_of_duplicates_group
,ROW_NUMBER()OVER(PARTITIONBY col_name ORDERBY col_name2)AS pos_in_group
FROMtable)SELECT*FROM cte
WHERE num_of_duplicates_group >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)>1ORDERBY count DESC
Стоит отметить, что это невыносимо медленно или может даже не завершиться, если запрашиваемый столбец не проиндексирован. В противном случае, я был в состоянии изменить , a.emailчтобы a.*и получить все идентификаторы строк с дубликатами.
NobleUplift
@NobleUplift О чем ты говоришь?
Майкл
@Michael Ну, так как это три года, я не могу тестировать ни на какой версии MySQL, которую я использовал, но я попробовал этот же запрос в базе данных, где у выбранного столбца не было индекса, поэтому потребовалось довольно много времени. несколько секунд, чтобы закончить. Изменение его SELECT DISTINCT a.*решено почти мгновенно.
NobleUplift
@NobleUplift Ах, хорошо. Я могу понять, что это медленно ... часть, о которой я беспокоюсь, это "может даже не закончить".
Майкл
@ Михаил, я не помню, по какой таблице в нашей системе мне нужно было выполнить этот запрос, но для таблиц с несколькими миллионами записей, которые они, вероятно, закончили бы, но за время, которое заняло так много времени, что я перестал видеть, когда это на самом деле закончится.
NobleUplift
1
Для удаления повторяющихся строк с несколькими полями сначала сопоставьте их новому уникальному ключу, который указан только для отдельных строк, а затем используйте команду «group by» для удаления дублирующихся строк с тем же новым уникальным ключом:
Create TEMPORARY table tmp select concat(f1,f2)as cfs,t1.*from mytable as t1;Createindex x_tmp_cfs on tmp(cfs);Createtable unduptable select f1,f2,...from tmp groupby cfs;
Почему бы не использовать CREATE TEMPORARY TABLE ...? Небольшое объяснение вашего решения было бы здорово.
maxhb
1
Один очень поздний вклад ... на тот случай, если он поможет кому-то в конце концов ... У меня была задача найти подходящие пары транзакций (фактически обе стороны переводов со счета на счет) в банковском приложении, чтобы определить, какие из них были 'from' и 'to' для каждой транзакции между счетами, поэтому мы получили следующее:
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
INNERJOIN 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
GROUPBY transactionid1
ORDERBY transactionid1;
Результатом является то, что он DuplicateResultsTableпредоставляет строки, содержащие совпадающие (т.е. дублирующие) транзакции, но он также предоставляет те же идентификаторы транзакций в обратном порядке во второй раз, когда он совпадает с той же парой, поэтому внешняя SELECTгруппа должна сгруппироваться по первому идентификатору транзакции, что делается с помощью LEASTи GREATESTубедитесь, что два идентификатора транзакции всегда находятся в одинаковом порядке в результатах, что делает его безопасным для GROUPпервого, тем самым устраняя все повторяющиеся совпадения. Пробежал почти миллион записей и выявил более 12 000 матчей за 2 секунды. Конечно, идентификатор транзакции является основным индексом, который действительно помог.
Ответы:
Сделать
SELECT
сGROUP BY
оговоркой. Допустим, имя - это столбец, в котором вы хотите найти дубликаты:Это вернет результат со значением имени в первом столбце и счетчиком того, сколько раз это значение появляется во втором столбце.
источник
GROUP_CONCAT(id)
и он будет перечислять идентификаторы. Смотрите мой ответ для примера.ERROR: column "c" does not exist LINE 1
?источник
IN()
/NOT IN()
.Этот запрос возвращает полные записи, а не только отдельные
varchar_column
.Этот запрос не использует
COUNT(*)
. Если дубликатов много, ониCOUNT(*)
дорогие и вам не нужно целоеCOUNT(*)
, вам просто нужно знать, есть ли две строки с одинаковым значением.varchar_column
Конечно, наличие индекса значительно ускорит этот запрос.источник
ORDER BY varchar_column DESC
в конец запроса.GROUP BY
иHAVING
возвращает только один из возможных дубликатов. Кроме того, производительность с индексированным полем вместоCOUNT(*)
, и возможностьORDER BY
группировать дубликаты записей.Составив ответ levik, чтобы получить идентификаторы дублирующихся строк, вы можете сделать это,
GROUP_CONCAT
если ваш сервер его поддерживает (это вернет список идентификаторов, разделенных запятыми).источник
SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...]
она включает встроенное редактирование и должна обновлять все задействованные строки (или, по крайней мере, первую совпадающую строку), но, к сожалению, редактирование генерирует ошибку Javascript. ..Предполагая, что ваша таблица называется TableABC, а столбец, который вам нужен, это Col, а первичный ключ к T1 - Key.
Преимущество этого подхода перед приведенным выше ответом заключается в том, что он дает ключ.
источник
источник
Чтобы узнать, сколько записей являются дубликатами в столбце имени в Employee, полезен следующий запрос;
источник
чтобы получить все данные, которые содержат дубликаты, я использовал это:
TableName = таблица, с которой вы работаете.
DupliactedData = дублированные данные, которые вы ищете.
источник
Мой последний запрос включал несколько ответов, которые мне помогли - объединение по группам, count & GROUP_CONCAT.
Это обеспечивает идентификатор обоих примеров (через запятую), нужный мне штрих-код и количество дубликатов.
Измените таблицу и столбцы соответственно.
источник
Я не вижу никаких подходов JOIN, которые имеют много применений с точки зрения дубликатов.
Этот подход дает вам реальные удвоенные результаты.
источник
Замените город своей таблицей. Замените имя на имя вашего поля
источник
Принимая @ maxyfc в ответ дальше, мне нужно , чтобы найти все из строк , которые были возвращены с повторяющимися значениями, так что я мог редактировать их в MySQL Workbench :
источник
Я видел приведенный выше результат, и запрос будет работать нормально, если вам нужно проверить значение одного столбца, которые являются дубликатами. Например, электронная почта.
Но если вам нужно проверить больше столбцов и хотите проверить комбинацию результата, этот запрос будет работать нормально:
источник
SELECT COUNT(CONCAT(userid,event,datetime)) AS total, userid, event, datetime FROM mytable GROUP BY CONCAT(userid, event, datetime ) HAVING total>1
Я предпочитаю использовать оконные функции (MySQL 8.0+) для поиска дубликатов, потому что я мог видеть всю строку:
DB Fiddle Demo
источник
источник
Далее будут найдены все product_id, которые используются более одного раза. Вы получаете только одну запись для каждого product_id.
Код взят из: http://chandreshrana.blogspot.in/2014/12/find-duplicate-records-based-on-any.html
источник
источник
источник
a.email
чтобыa.*
и получить все идентификаторы строк с дубликатами.SELECT DISTINCT a.*
решено почти мгновенно.Для удаления повторяющихся строк с несколькими полями сначала сопоставьте их новому уникальному ключу, который указан только для отдельных строк, а затем используйте команду «group by» для удаления дублирующихся строк с тем же новым уникальным ключом:
источник
CREATE TEMPORARY TABLE ...
? Небольшое объяснение вашего решения было бы здорово.Один очень поздний вклад ... на тот случай, если он поможет кому-то в конце концов ... У меня была задача найти подходящие пары транзакций (фактически обе стороны переводов со счета на счет) в банковском приложении, чтобы определить, какие из них были 'from' и 'to' для каждой транзакции между счетами, поэтому мы получили следующее:
Результатом является то, что он
DuplicateResultsTable
предоставляет строки, содержащие совпадающие (т.е. дублирующие) транзакции, но он также предоставляет те же идентификаторы транзакций в обратном порядке во второй раз, когда он совпадает с той же парой, поэтому внешняяSELECT
группа должна сгруппироваться по первому идентификатору транзакции, что делается с помощьюLEAST
иGREATEST
убедитесь, что два идентификатора транзакции всегда находятся в одинаковом порядке в результатах, что делает его безопасным дляGROUP
первого, тем самым устраняя все повторяющиеся совпадения. Пробежал почти миллион записей и выявил более 12 000 матчей за 2 секунды. Конечно, идентификатор транзакции является основным индексом, который действительно помог.источник
источник
источник
Если вы хотите удалить дубликаты, используйте
DISTINCT
В противном случае используйте этот запрос:
SELECT users.*,COUNT(user_ID) as user FROM users GROUP BY user_name HAVING user > 1;
источник
Попробуйте использовать этот запрос:
источник