Ich habe eine Tabelle mit einer Varchar-Spalte und möchte alle Datensätze mit doppelten Werten in dieser Spalte finden. Was ist die beste Abfrage, mit der ich die Duplikate finden kann?
Da Sie erwähnt haben, dass Sie alle Datensätze finden, gehe ich davon aus, dass Sie die SCHLÜSSEL sowie die duplizierten WERTE in dieser varchar-Spalte kennen müssen.
TechTravelThink
Ich kann die Schlüssel leicht genug finden, nachdem ich die Werte erhalten habe. Ich möchte wirklich nur eine Liste aller doppelten Werte.
Jon Tackabury
Antworten:
1522
Mach ein SELECTmit einer GROUP BYKlausel. Angenommen, Name ist die Spalte, in der Sie Duplikate finden möchten:
SELECT name, COUNT(*) c FROMtableGROUPBY name HAVING c >1;
Dies gibt ein Ergebnis mit dem Namenswert in der ersten Spalte und einer Zählung zurück, wie oft dieser Wert in der zweiten Spalte angezeigt wird.
Aber wie ist das nützlich, wenn Sie die IDs der Zeilen mit doppelten Werten nicht erhalten können? Ja, Sie können für jeden doppelten Wert eine neue Abfrage durchführen. Ist es jedoch möglich, die doppelten Werte einfach aufzulisten?
NobleUplift
23
@NobleUplift Sie können eine ausführen GROUP_CONCAT(id)und es werden die IDs aufgelistet . Siehe meine Antwort für ein Beispiel.
Matt Rardon
5
Was würde es bedeuten, wenn es heißt ERROR: column "c" does not exist LINE 1?
Benutzer
15
Ich bin verwirrt, warum dies die akzeptierte Antwort ist und warum es so viele positive Stimmen gibt. Das OP fragte: "Ich möchte alle Datensätze mit doppelten Werten in dieser Spalte finden." Diese Antwort gibt eine Zählungstabelle zurück. -1
Monica Heddneck
4
Für diejenigen, die nicht verstehen, wie HAVING funktioniert - es ist einfach ein Filter für die Ergebnismenge, also geschieht dies nach der Hauptabfrage.
John Hunt
236
SELECT varchar_col
FROMtableGROUPBY varchar_col
HAVING COUNT(*)>1;
Überlegen gegenüber der Antwort von @ levik, da keine zusätzliche Spalte hinzugefügt wird. Macht es nützlich für die Verwendung mit IN()/ NOT IN().
Wmassingham
172
SELECT*FROM mytable mto
WHEREEXISTS(SELECT1FROM mytable mti
WHERE mti.varchar_column = mto.varchar_column
LIMIT 1,1)
Diese Abfrage gibt vollständige Datensätze zurück, nicht nur eindeutige varchar_column.
Diese Abfrage wird nicht verwendet COUNT(*). Wenn es viele Duplikate gibt, COUNT(*)teuer ist und Sie nicht das Ganze benötigen COUNT(*), müssen Sie nur wissen, ob es zwei Zeilen mit demselben Wert gibt.
Wenn Sie einen Index für haben, varchar_columnwird diese Abfrage natürlich erheblich beschleunigt.
Sehr gut. Ich ORDER BY varchar_column DESChabe am Ende der Abfrage hinzugefügt .
Trante
8
Dies sollte die akzeptierte Antwort, wie sein GROUP BYund HAVINGgibt nur eine der möglichen Duplikate. Außerdem Leistung mit indiziertem Feld anstelle von COUNT(*)und die Möglichkeit, ORDER BYdoppelte Datensätze zu gruppieren.
Rémi Breton
1
Wie in den obigen Kommentaren angegeben, können Sie mit dieser Abfrage alle doppelten Zeilen auflisten. Sehr hilfreich.
TryHarder
4
Wenn ich das betrachte, verstehe ich nicht, wie es überhaupt funktionieren würde. Wird die innere Bedingung nicht immer zutreffen, da jede Zeile in der äußeren Tabelle auch in der inneren Tabelle verfügbar ist und daher jede Zeile immer mindestens mit sich selbst übereinstimmt? Ich habe die Abfrage ausprobiert und das von mir vermutete Ergebnis erhalten - jede Zeile wurde zurückgegeben. Aber bei so vielen positiven Stimmen bezweifle ich mich. Fehlt der inneren Abfrage nicht etwas wie "AND mto.id <> mti.id"? Es funktioniert für mich, wenn ich das hinzufüge.
Clox
2
@ Quassnoi In Ordnung. Ich habe versucht, es auf sqlfiddle zu stellen, aber ich habe aufgegeben, da jede Abfrage, die ich ausführen möchte, abgesehen vom Erstellen des Schemas eine Zeitüberschreitung aufweist. Ich habe herausgefunden, dass das Entfernen von "EXISTS" auch dazu führt, dass die Abfrage für mich korrekt funktioniert.
Clox
144
Aufbauend auf der Antwort von levik, um die IDs der doppelten Zeilen zu erhalten, können Sie eine ausführen, GROUP_CONCATwenn Ihr Server dies unterstützt (dies gibt eine durch Kommas getrennte Liste von IDs zurück).
SELECT GROUP_CONCAT(id), name, COUNT(*) c FROM documents GROUPBY name HAVING c >1;
Die ganze Zeit ohne etwas über GROUP_CONCAT () zu wissen! sehr sehr nützlich.
Aesede
Wirklich geschätzt Matt. Das ist wirklich hilfreich! Für diejenigen, die versuchen, in phpmyadmin zu aktualisieren, wenn Sie die ID zusammen mit der folgenden Funktion belassen: Sie aktiviert SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...]die Inline-Bearbeitung und sollte alle beteiligten Zeilen aktualisieren (oder zumindest die erste übereinstimmende), aber leider erzeugt die Bearbeitung einen Javascript-Fehler. ..
Armfoot
Wie würden Sie dann berechnen, wie viele IDs dupliziert werden?
CMCDragonkai
2
Wie bekomme ich nicht alle IDs gruppiert, sondern von Anfang bis Ende aufgelistet? mit all ihren jeweiligen Werten in den Spalten neben ihnen? Anstatt es zu gruppieren, werden nur ID 1 und sein Wert, ID 2 und sein Wert angezeigt. AUCH wenn die Werte für die ID gleich sind.
MailBlade
1
Sehr hilfreiche Antwort, dies sollte top sein, damit mehr Leute es sehen. Ich erinnere mich, wie viel Schmerz ich durch das Erstellen solcher Listen hatte, und es war die ganze Zeit als Befehl verfügbar.
John
13
Angenommen, Ihre Tabelle heißt TableABC und die gewünschte Spalte 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 besteht darin, dass er den Schlüssel gibt.
+1 Weil es praktisch ist. Ironischerweise enthält das Ergebnis selbst Duplikate (es listet a und b, dann b und a auf)
Fabien Snauwaert
2
@ FabienSnauwaert Sie können einige der Duplikate entfernen, indem Sie weniger als (oder mehr als) vergleichen
Michael
@TechTravelThink Ihre Antwort ist sehr klar, danke dafür, aber bei einer großen Tabelle dauert es einige Zeit (ca. 2 Minuten bei mehr als 20'000 Einträgen) und nach 25 ersten Ergebnissen, wenn ich auf die nächste klicke, zeigt phpmyadmin den Fehler "# 1052 - Spalte 'id' in der
Bestellklausel
12
SELECT*FROM`dps`WHERE pid IN(SELECT pid FROM`dps`GROUPBY pid HAVING COUNT(pid)>1)
Nein, denn dies ist wahrscheinlich das langsamste von allen. Unterauswahlen sind notorisch langsam, da sie für jede zurückgegebene Zeile ausgeführt werden.
Oddman
10
Um herauszufinden, wie viele Datensätze in der Namensspalte des Mitarbeiters doppelt vorhanden sind, ist die folgende Abfrage hilfreich.
Select name from employee groupby name having count(*)>1;
Zu Ihrer Information - Sie sollten "eindeutiges Somecol .. auswählen", wenn möglicherweise mehr als ein doppelter Datensatz vorhanden ist. Andernfalls enthalten die Ergebnisse Duplikate der gefundenen doppelten Zeilen.
Drew
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
Ersetzen Sie die Stadt durch Ihren Tisch. Ersetzen Sie den Namen durch Ihren Feldnamen
Unter @ maxyfc der Antwort weiter, ich brauchte finden alle der Zeilen , die mit den doppelten Werten zurückgegeben wurden, so dass ich sie in bearbeiten könnte MySQL Workbench :
SELECT*FROMtableWHERE field IN(SELECT field FROMtableGROUPBY field HAVING count(*)>1)ORDERBY field
Ich habe das obige Ergebnis gesehen und die Abfrage funktioniert einwandfrei, wenn Sie doppelte Spaltenwerte überprüfen müssen. Zum Beispiel E-Mail.
Wenn Sie jedoch mit mehr Spalten prüfen müssen und die Kombination des Ergebnisses überprüfen möchten, funktioniert diese Abfrage einwandfrei:
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)
Genau das, was gebraucht wurde! Hier meine Anfrage, 3 Felder auf Duplikate zu überprüfen:SELECT COUNT(CONCAT(userid,event,datetime)) AS total, userid, event, datetime FROM mytable GROUP BY CONCAT(userid, event, datetime ) HAVING total>1
Kai Noack
4
Ich bevorzuge die Verwendung von Fensterfunktionen (MySQL 8.0+), um Duplikate zu finden, da ich die gesamte Zeile sehen konnte:
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
Es ist erwähnenswert, dass dies unerträglich langsam ist oder möglicherweise nicht einmal beendet wird, wenn die abgefragte Spalte nicht indiziert ist. Ansonsten konnte ich ändern a.emailzu a.*und alle die IDs der Zeilen mit Duplikaten zu erhalten.
NobleUplift
@NobleUplift Worüber sprichst du?
Michael
@Michael Nun, da dies drei Jahre alt ist, kann ich nicht testen, welche Version von MySQL ich verwendet habe, aber ich habe dieselbe Abfrage in einer Datenbank versucht, in der die von mir ausgewählte Spalte keinen Index hatte, also hat es ziemlich lange gedauert ein paar Sekunden bis zum Ende. Ändern Sie es in SELECT DISTINCT a.*fast sofort gelöst.
NobleUplift
@ NobleUplift Ah ok. Ich kann verstehen, dass es langsam ist ... der Teil, über den ich mir Sorgen mache, ist "vielleicht nicht einmal fertig".
Michael
@Michael Ich erinnere mich nicht, auf welcher Tabelle in unserem System ich diese Abfrage ausführen musste, aber für diejenigen mit ein paar Millionen Datensätzen wären sie wahrscheinlich fertig, aber in einer Zeit, die so lange dauerte, dass ich es aufgab zu sehen, wann es würde tatsächlich enden.
NobleUplift
1
Um doppelte Zeilen mit mehreren Feldern zu entfernen, müssen Sie sie zuerst auf den neuen eindeutigen Schlüssel streichen, der für die einzigen unterschiedlichen Zeilen angegeben ist, und dann mit dem Befehl "group by" doppelte Zeilen mit demselben neuen eindeutigen Schlüssel entfernen:
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;
Warum nicht verwenden CREATE TEMPORARY TABLE ...? Eine kleine Erklärung Ihrer Lösung wäre großartig.
Maxhb
1
Ein sehr später Beitrag ... für den Fall, dass es jemandem hilft, auf der ganzen Linie zu warten ... Ich hatte die Aufgabe, passende Transaktionspaare (eigentlich beide Seiten von Konto-zu-Konto-Überweisungen) in einer Bank-App zu finden, um zu identifizieren, welche waren die 'von' und 'bis' für jede Transaktion zwischen Kontotransfers, so dass wir am Ende folgendes hatten:
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;
Das Ergebnis ist, dass die DuplicateResultsTableZeilen Zeilen enthalten, die übereinstimmende (dh doppelte) Transaktionen enthalten, aber auch die gleichen Transaktions-IDs in umgekehrter Reihenfolge bereitstellen, wenn sie zum zweiten Mal mit demselben Paar übereinstimmen, sodass die äußere SELECTnach der ersten Transaktions-ID gruppiert werden kann durch die NutzungLEAST und GREATESTsicherstellen, dass die beiden Transaktions-IDs in den Ergebnissen immer in derselben Reihenfolge sind, was es sicher macht, bis GROUPzum ersten zu gehen, wodurch alle doppelten Übereinstimmungen eliminiert werden. Durchlief fast eine Million Rekorde und identifizierte mehr als 12.000 Spiele in knapp 2 Sekunden. Natürlich ist die Transaktions-ID der Primärindex, was wirklich geholfen hat.
Antworten:
Mach ein
SELECT
mit einerGROUP BY
Klausel. Angenommen, Name ist die Spalte, in der Sie Duplikate finden möchten:Dies gibt ein Ergebnis mit dem Namenswert in der ersten Spalte und einer Zählung zurück, wie oft dieser Wert in der zweiten Spalte angezeigt wird.
quelle
GROUP_CONCAT(id)
und es werden die IDs aufgelistet . Siehe meine Antwort für ein Beispiel.ERROR: column "c" does not exist LINE 1
?quelle
IN()
/NOT IN()
.Diese Abfrage gibt vollständige Datensätze zurück, nicht nur eindeutige
varchar_column
.Diese Abfrage wird nicht verwendet
COUNT(*)
. Wenn es viele Duplikate gibt,COUNT(*)
teuer ist und Sie nicht das Ganze benötigenCOUNT(*)
, müssen Sie nur wissen, ob es zwei Zeilen mit demselben Wert gibt.Wenn Sie einen Index für haben,
varchar_column
wird diese Abfrage natürlich erheblich beschleunigt.quelle
ORDER BY varchar_column DESC
habe am Ende der Abfrage hinzugefügt .GROUP BY
undHAVING
gibt nur eine der möglichen Duplikate. Außerdem Leistung mit indiziertem Feld anstelle vonCOUNT(*)
und die Möglichkeit,ORDER BY
doppelte Datensätze zu gruppieren.Aufbauend auf der Antwort von levik, um die IDs der doppelten Zeilen zu erhalten, können Sie eine ausführen,
GROUP_CONCAT
wenn Ihr Server dies unterstützt (dies gibt eine durch Kommas getrennte Liste von IDs zurück).quelle
SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...]
die Inline-Bearbeitung und sollte alle beteiligten Zeilen aktualisieren (oder zumindest die erste übereinstimmende), aber leider erzeugt die Bearbeitung einen Javascript-Fehler. ..Angenommen, Ihre Tabelle heißt TableABC und die gewünschte Spalte ist Col und der Primärschlüssel für T1 ist Key.
Der Vorteil dieses Ansatzes gegenüber der obigen Antwort besteht darin, dass er den Schlüssel gibt.
quelle
quelle
Um herauszufinden, wie viele Datensätze in der Namensspalte des Mitarbeiters doppelt vorhanden sind, ist die folgende Abfrage hilfreich.
quelle
Um alle Daten zu erhalten, die Duplikate enthalten, habe ich Folgendes verwendet:
TableName = die Tabelle, mit der Sie arbeiten.
DupliactedData = die duplizierten Daten, nach denen Sie suchen.
quelle
Meine letzte Abfrage enthielt einige der Antworten, die hier geholfen haben - das Kombinieren von Gruppieren nach, Zählen & GROUP_CONCAT.
Dies gibt die ID beider Beispiele (durch Kommas getrennt), den von mir benötigten Barcode und die Anzahl der Duplikate an.
Ändern Sie Tabelle und Spalten entsprechend.
quelle
Ich sehe keine JOIN-Ansätze, die in Bezug auf Duplikate viele Verwendungszwecke haben.
Dieser Ansatz liefert Ihnen tatsächlich doppelte Ergebnisse.
quelle
Ersetzen Sie die Stadt durch Ihren Tisch. Ersetzen Sie den Namen durch Ihren Feldnamen
quelle
Unter @ maxyfc der Antwort weiter, ich brauchte finden alle der Zeilen , die mit den doppelten Werten zurückgegeben wurden, so dass ich sie in bearbeiten könnte MySQL Workbench :
quelle
Ich habe das obige Ergebnis gesehen und die Abfrage funktioniert einwandfrei, wenn Sie doppelte Spaltenwerte überprüfen müssen. Zum Beispiel E-Mail.
Wenn Sie jedoch mit mehr Spalten prüfen müssen und die Kombination des Ergebnisses überprüfen möchten, funktioniert diese Abfrage einwandfrei:
quelle
SELECT COUNT(CONCAT(userid,event,datetime)) AS total, userid, event, datetime FROM mytable GROUP BY CONCAT(userid, event, datetime ) HAVING total>1
Ich bevorzuge die Verwendung von Fensterfunktionen (MySQL 8.0+), um Duplikate zu finden, da ich die gesamte Zeile sehen konnte:
DB Fiddle Demo
quelle
quelle
Im Folgenden finden Sie alle product_id, die mehrmals verwendet werden. Sie erhalten nur einen einzigen Datensatz für jede product_id.
Code entnommen aus: http://chandreshrana.blogspot.in/2014/12/find-duplicate-records-based-on-any.html
quelle
quelle
quelle
a.email
zua.*
und alle die IDs der Zeilen mit Duplikaten zu erhalten.SELECT DISTINCT a.*
fast sofort gelöst.Um doppelte Zeilen mit mehreren Feldern zu entfernen, müssen Sie sie zuerst auf den neuen eindeutigen Schlüssel streichen, der für die einzigen unterschiedlichen Zeilen angegeben ist, und dann mit dem Befehl "group by" doppelte Zeilen mit demselben neuen eindeutigen Schlüssel entfernen:
quelle
CREATE TEMPORARY TABLE ...
? Eine kleine Erklärung Ihrer Lösung wäre großartig.Ein sehr später Beitrag ... für den Fall, dass es jemandem hilft, auf der ganzen Linie zu warten ... Ich hatte die Aufgabe, passende Transaktionspaare (eigentlich beide Seiten von Konto-zu-Konto-Überweisungen) in einer Bank-App zu finden, um zu identifizieren, welche waren die 'von' und 'bis' für jede Transaktion zwischen Kontotransfers, so dass wir am Ende folgendes hatten:
Das Ergebnis ist, dass die
DuplicateResultsTable
Zeilen Zeilen enthalten, die übereinstimmende (dh doppelte) Transaktionen enthalten, aber auch die gleichen Transaktions-IDs in umgekehrter Reihenfolge bereitstellen, wenn sie zum zweiten Mal mit demselben Paar übereinstimmen, sodass die äußereSELECT
nach der ersten Transaktions-ID gruppiert werden kann durch die NutzungLEAST
undGREATEST
sicherstellen, dass die beiden Transaktions-IDs in den Ergebnissen immer in derselben Reihenfolge sind, was es sicher macht, bisGROUP
zum ersten zu gehen, wodurch alle doppelten Übereinstimmungen eliminiert werden. Durchlief fast eine Million Rekorde und identifizierte mehr als 12.000 Spiele in knapp 2 Sekunden. Natürlich ist die Transaktions-ID der Primärindex, was wirklich geholfen hat.quelle
quelle
quelle
Wenn Sie doppelte Verwendung entfernen möchten
DISTINCT
Andernfalls verwenden Sie diese Abfrage:
SELECT users.*,COUNT(user_ID) as user FROM users GROUP BY user_name HAVING user > 1;
quelle
Versuchen Sie es mit dieser Abfrage:
quelle