it-swarm.com.ru

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

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

671
Jon Tackabury

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

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

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

1346
levik
SELECT varchar_col
FROM table
GROUP BY varchar_col
HAVING COUNT(*) > 1;
200
maxyfc
SELECT  *
FROM    mytable mto
WHERE   EXISTS
        (
        SELECT  1
        FROM    mytable mti
        WHERE   mti.varchar_column = mto.varchar_column
        LIMIT 1, 1
        )

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

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

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

149
Quassnoi

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

SELECT GROUP_CONCAT(id), name, COUNT(*) c FROM documents GROUP BY name HAVING c > 1;
116
Matt Rardon
SELECT * 
FROM `dps` 
WHERE pid IN (SELECT pid FROM `dps` GROUP BY pid HAVING COUNT(pid)>1)
12
strustam

Предполагая, что ваша таблица называется 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

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

11
TechTravelThink

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

Select name from employee group by name having count(*)>1;
9
user5599549
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

Замените город вашей таблицей. Замените name на ваше имя поля

7
Lalit Patel

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

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

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

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

6
Jonathan

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

Этот подход дает вам реальные удвоенные результаты.

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
6
Adam Fischer

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

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

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)
5
user2235601

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

SELECT * FROM table
   WHERE field IN (
     SELECT field FROM table GROUP BY field HAVING count(*) > 1
   ) ORDER BY field
4
AbsoluteƵERØ
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
3
magesh

Далее будут найдены все 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

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

INSERT INTO tbl_master
    (`id`, `email`) VALUES
    (1, '[email protected]'),
    (2, '[email protected]'),
    (3, '[email protected]'),
    (4, '[email protected]'),
    (5, '[email protected]');

QUERY : SELECT id, email FROM tbl_master
WHERE email IN (SELECT email FROM tbl_master GROUP BY email HAVING COUNT(id) > 1)
3
Bijesh Sheth
SELECT DISTINCT a.email FROM `users` a LEFT JOIN `users` b ON a.email = b.email WHERE a.id != b.id;
2
Pawel Furmaniak

Один очень поздний вклад ... на тот случай, если он поможет кому-нибудь еще пообщаться ... У меня была задача найти подходящие пары транзакций (фактически обе стороны переводов со счета на счет) в банковском приложении, чтобы определить, какие из них были '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
    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 предоставляет строки, содержащие совпадающие (т. Е. Дублирующие) транзакции, но он также предоставляет идентичные идентификаторы транзакций в обратном порядке во второй раз, когда совпадает с той же парой, поэтому внешняя SELECT существует для группировки по первому идентификатору транзакции, который это делается с помощью LEAST и GREATEST, чтобы убедиться, что два идентификатора транзакции всегда находятся в одинаковом порядке в результатах, что делает безопасным GROUP первым, тем самым устраняя все повторяющиеся совпадения. Пробежал почти миллион записей и выявил более 12 000 матчей за 2 секунды. Конечно, идентификатор транзакции является основным индексом, который действительно помог.

1
fortyninthnet

Для удаления повторяющихся строк с несколькими полями сначала можно сопоставить их с новым уникальным ключом, который указан только для отдельных строк, а затем использовать команду «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;
1
irshst

Если вы хотите удалить дубликаты, используйте DISTINCT 

В противном случае используйте этот запрос:

SELECT users.*,COUNT(user_ID) as user FROM users GROUP BY user_name HAVING user > 1;

1
Hassan Latif Butt
Select column_name, column_name1,column_name2, count(1) as temp from table_name group by column_name having temp > 1
1
Vipin Jain

Я предпочитаю использовать оконные функции (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;

БД Fiddle Демонстрация

1
Lukasz Szozda

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

SELECT * FROM TableName INNER JOIN(
  SELECT DupliactedData FROM TableName GROUP BY DupliactedData HAVING COUNT(DupliactedData) > 1 order by DupliactedData)
  temp ON TableName.DupliactedData = temp.DupliactedData;

TableName = таблица, с которой вы работаете.

DupliactedData = дублированные данные, которые вы ищете.

0
udi

Попробуйте использовать этот запрос:

SELECT name, COUNT(*) value_count FROM company_master GROUP BY name HAVING value_count > 1;
0
Atul Akabari
SELECT ColumnA, COUNT( * )
FROM Table
GROUP BY ColumnA
HAVING COUNT( * ) > 1
0
Scott Ferguson