Suchen nach doppelten Werten in MySQL

Ich habe eine Tabelle mit einer varchar Spalte, und ich möchte alle Datensätze finden, die doppelte Werte in dieser Spalte haben. Was ist die beste Abfrage, die ich verwenden kann, um die Duplikate zu finden?

SELECT Sie eine SELECT mit einer GROUP BY Klausel aus. Angenommen, name ist die Spalte, in der Duplikate suchen möchten:

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

Dies wird ein Ergebnis mit dem Namen Wert in der ersten Spalte und eine Anzahl von wie oft dieser Wert in der zweiten Spalte angezeigt.

 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 ) 

Diese Abfrage gibt vollständige Datensätze zurück, nicht nur unterschiedliche varchar_column .

Diese Abfrage verwendet COUNT(*) . Wenn es viele Duplikate gibt, ist COUNT(*) teuer, und Sie brauchen nicht den ganzen COUNT(*) , Sie müssen nur wissen, ob es zwei Zeilen mit demselben Wert gibt.

Ein Index auf varchar_column wird diese Abfrage natürlich erheblich beschleunigen.

Ausgehend von leviks Antwort, um die IDs der doppelten Zeilen zu erhalten, können Sie eine GROUP_CONCAT wenn Ihr Server dies unterstützt (dies wird eine durch Komma getrennte Liste von IDs zurückgeben).

 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) 

Angenommen, Ihre Tabelle heißt TableABC und die Spalte, die Sie haben möchten, ist Col und der Primärschlüssel für T1 ist Key.

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

Der Vorteil dieses Ansatzes gegenüber der obigen Antwort ist, dass es den Schlüssel gibt.

Um zu ermitteln, wie viele Datensätze in der Spalte Name in Employee doppelt vorhanden sind, ist die folgende Abfrage hilfreich.

 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 

Ersetzen Sie die Stadt durch Ihre Tabelle. Ersetzen Sie den Namen durch Ihren Feldnamen

Meine letzte Anfrage enthielt ein paar der Antworten, die dabei geholfen haben – Kombination von Gruppe, Count & GROUP_CONCAT.

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

Dies liefert die ID beider Beispiele (durch Komma getrennt), den benötigten Barcode und die Anzahl der Duplikate.

Ändern Sie Tabelle und Spalten entsprechend.

Ich sah das obige Ergebnis und Abfrage funktioniert gut, wenn Sie einzelne Spaltenwert überprüfen müssen, die doppelt sind. Zum Beispiel E-Mail.

Aber wenn Sie mit mehr Spalten überprüfen müssen und die Kombination des Ergebnisses überprüfen möchten, wird diese Abfrage funktionieren:

 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 

Im Folgenden finden Sie alle product_id, die mehr als einmal verwendet werden. Sie erhalten nur einen einzelnen Datensatz für jede product_id.

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

Code entnommen von: http://chandreshrana.blogspot.in/2014/12/find-duplicate-records-based-on-anyy.html

Ich sehe keine JOIN-Ansätze, die in Bezug auf Duplikate viele Verwendungsmöglichkeiten haben.

Dieser Aproach gibt Ihnen tatsächlich doppelte Ergebnisse.

 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, '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) 

Um die Antwort von @ maxyfc weiterzuführen , musste ich alle Zeilen finden, die mit den doppelten Werten zurückgegeben wurden, damit ich sie in MySQL Workbench bearbeiten konnte:

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

Um doppelte Zeilen mit mehreren Feldern zu entfernen, müssen Sie sie zuerst dem neuen eindeutigen Schlüssel zuordnen, der für die einzigen eindeutigen Zeilen angegeben ist. Verwenden Sie dann den Befehl “Gruppieren nach”, um doppelte Zeilen mit demselben neuen eindeutigen Schlüssel zu entfernen:

 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; 

Ein sehr später Beitrag … für den Fall, dass es jemandem weiterhilft … Ich hatte die Aufgabe, passende Paare von Transaktionen (eigentlich beide Seiten von Konto-zu-Konto-Überweisungen) in einer Banking-App zu finden, um herauszufinden, welche waren das “von” und “zu” für jede Inter-Konto-Übertragung, so dass wir damit endete:

 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; 

Das Ergebnis ist, dass die DuplicateResultsTable Zeilen enthält, die übereinstimmende (dh doppelte) Transaktionen enthalten, aber dieselbe Transaktions-ID beim zweiten Mal, wenn sie dem gleichen Paar entspricht, bereitstellt, so dass die äußere SELECT Gruppierung nach der ersten Transaktions-ID gruppiert wird Durch die Verwendung von LEAST und GREATEST sichergestellt, dass die beiden Transaktions- LEAST in den Ergebnissen immer in der gleichen Reihenfolge sind, wodurch die GROUP nach der ersten LEAST sicher ist und somit alle doppelten Übereinstimmungen eliminiert werden. Durchlief fast eine Million Datensätze und identifizierte 12.000 Treffer in weniger als 2 Sekunden. Natürlich ist die transactionid der primäre Index, der wirklich geholfen hat.

 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 

Ich bevorzuge windowed functionen (MySQL 8.0+), um Duplikate zu finden, weil ich die ganze Zeile sehen könnte:

 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