Trovare valori duplicati in MySQL

Ho una tabella con una colonna varchar e vorrei trovare tutti i record che hanno valori duplicati in questa colonna. Qual è la migliore query che posso usare per trovare i duplicati?

Fai un SELECT con una clausola GROUP BY . Diciamo che il nome è la colonna in cui si desidera trovare i duplicati in:

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

Ciò restituirà un risultato con il valore del nome nella prima colonna e un conteggio di quante volte quel valore appare nel secondo.

 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 ) 

Questa query restituisce i record completi, non solo quelli distinti di varchar_column .

Questa query non utilizza COUNT(*) . Se ci sono molti duplicati, COUNT(*) è costoso e non è necessario l’intero COUNT(*) , è sufficiente sapere se ci sono due righe con lo stesso valore.

Avere un indice su varchar_column , naturalmente, accelera notevolmente questa query.

Partendo dalla risposta di levik per ottenere gli ID delle righe duplicate, puoi fare un GROUP_CONCAT se il tuo server lo supporta (questo restituirà un elenco di id separati da virgole).

 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) 

Supponendo che la tua tabella sia denominata TableABC e la colonna che desideri sia Col e la chiave primaria di T1 sia Key.

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

Il vantaggio di questo approccio rispetto alla risposta di cui sopra è che dà la chiave.

Per trovare quanti record sono duplicati nella colonna del nome in Dipendente, la query sottostante è utile;

 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 

Sostituisci la città con il tuo tavolo. Sostituisci il nome con il nome del tuo campo

La mia ultima domanda ha incluso alcune delle risposte che hanno aiutato: la combinazione di gruppo, conteggio e GROUP_CONCAT.

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

Questo fornisce l’id di entrambi gli esempi (separati da virgola), il codice a barre di cui avevo bisogno e quanti duplicati.

Modificare la tabella e le colonne di conseguenza.

Ho visto il risultato sopra riportato e la query funzionerà correttamente se è necessario verificare il valore di una singola colonna che è duplicato. Ad esempio email.

Ma se hai bisogno di controllare con più colonne e vuoi controllare la combinazione del risultato, questa query funzionerà correttamente:

 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 

Quanto segue troverà tutti i product_id che vengono utilizzati più di una volta. Ottieni solo un singolo record per ogni product_id.

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

Codice tratto da: http://chandreshrana.blogspot.in/2014/12/find-duplicate-records-based-on-any.html

Non vedo alcun messaggio di JOIN, che ha molti usi in termini di duplicati.

Questo aproeach ti dà risultati raddoppiati reali.

 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; 
 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) 

Prendendo ulteriormente la risposta di @ maxyfc , avevo bisogno di trovare tutte le righe che sono state restituite con i valori duplicati, così ho potuto modificarle in MySQL Workbench :

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

Per rimuovere le righe duplicate con più campi, prima cancella la nuova chiave univoca che è specificata per le sole righe distinte, quindi usa il comando “raggruppa per” per rimuovere le righe duplicate con la stessa nuova chiave univoca:

 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; 

Un contributo molto tardivo … nel caso in cui aiuti qualcuno in futuro … ho avuto il compito di trovare coppie di transazioni corrispondenti (in realtà entrambi i lati dei trasferimenti da conto a conto) in un’applicazione bancaria, per identificare quali erano il ‘da’ e ‘a’ per ogni transazione di trasferimento tra conti, quindi abbiamo finito con questo:

 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; 

Il risultato è che DuplicateResultsTable fornisce righe contenenti transazioni di corrispondenza (cioè duplicate), ma fornisce anche gli stessi ID di transazione al contrario la seconda volta che corrisponde alla stessa coppia, quindi SELECT esterno è lì per raggruppare il primo ID di transazione, che viene eseguito utilizzando LEAST e GREATEST per assicurarsi che i due transactionid siano sempre nello stesso ordine nei risultati, il che rende sicuro GROUP per il primo, eliminando così tutte le corrispondenze duplicate. Ha superato quasi un milione di record e identificato più di 12.000 partite in meno di 2 secondi. Naturalmente il transactionid è l’indice primario, che ha davvero aiutato.

 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 

Preferisco usare le funzioni con windows (MySQL 8.0+) per trovare i duplicati perché potrei vedere l’intera riga:

 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