2010-09-08 19 views
13

Ich habe eine Tabelle mit Daten und es gibt viele doppelte Einträge von Benutzereinreichungen.Entfernen Sie doppelte Zeilen mit der ältesten Zeile Nur?

Ich möchte alle Duplikatzeilen basierend auf dem Feld subscriberEmail löschen, nur die ursprüngliche Einreichung zu verlassen.

Mit anderen Worten, ich möchte nach allen doppelten E-Mails suchen und diese Zeilen löschen, nur das Original zurücklassen.

Wie kann ich dies tun, ohne Tabellen zu tauschen?
Meine Tabelle enthält eindeutige IDs für jede Zeile.

+0

sollten Sie markiere eine Antwort als "akzeptiert" :-) – watery

Antwort

27

Da Sie die ID-Spalte als Indikator verwenden, von denen Datensatz ‚Original‘ ist:

delete x 
from myTable x 
join myTable z on x.subscriberEmail = z.subscriberEmail 
where x.id > z.id 

So bleibt ein Datensatz pro E-Mail-Adresse.

bearbeiten hinzuzufügen:

die Abfrage oben Um zu erklären, ...

Die Idee hier ist die Tabelle mit sich selbst zu verbinden. Tue so, als hättest du zwei Kopien der Tabelle, die jeweils etwas anderes benannt haben. Dann können Sie sie miteinander vergleichen und die niedrigste ID oder für jede E-Mail-Adresse finden. Sie sehen dann die doppelten Datensätze, die später erstellt wurden, und könnten sie löschen. (Ich visualisierte Excel, wenn ich darüber nachdachte.)

Um diese Operation für eine Tabelle auszuführen, vergleichen Sie sie mit sich selbst und können Sie jede Seite identifizieren, indem Sie Tabellenaliasnamen verwenden. x ist ein Tabellenalias. Es ist in der from Klausel wie folgt zugeordnet: from <table> <alias>. x kann jetzt an anderer Stelle in derselben Abfrage verwendet werden, um auf diese Tabelle als Verknüpfung zu verweisen.

delete x startet die Abfrage mit unserer Aktion und Ziel. Wir werden eine Abfrage ausführen, um Datensätze aus mehreren Tabellen auszuwählen, und wir möchten Datensätze löschen, die in x angezeigt werden.

Aliase werden verwendet, um auf beide "Instanzen" der Tabelle zu verweisen. from myTable x join myTable z on x.subscriberEmail = z.subscriberEmail bumps den Tisch gegen sich selbst, wo die E-Mails übereinstimmen. Ohne die where-Klausel, die folgt, würde jeder Datensatz so ausgewählt werden, wie er mit sich selbst verbunden werden könnte.

Die Klausel where begrenzt die ausgewählten Datensätze. where x.id > z.id ermöglicht die "Instanz" aliased x enthalten nur die Datensätze, die E-Mails entsprechen, aber einen höheren Wert id haben. Die Daten, die Sie wirklich in der Tabelle möchten, eindeutige E-Mail-Adressen (mit der niedrigsten ID) sind nicht Bestandteil von x und werden nicht gelöscht. Die einzigen Datensätze in x werden doppelte Datensätze (E-Mail-Adressen) sein, die eine höhere id als der ursprüngliche Datensatz für diese E-Mail-Adresse haben.

Die Join und wo Klauseln in diesem Fall kombiniert werden könnten:

delete x 
    from myTable x 
    join myTable z 
    on x.subscriberEmail = z.subscriberEmail 
     and x.id > z.id 

Dubletten zu verhindern, sollten Sie die subscriberEmail Spalte eine UNIQUE-indizierte Spalte zu machen.

+0

Hey, ich verstehe nicht was X darin ist und wo das Datum eingegeben wird. Ich könnte ID verwenden, da für jedes Datum oder jedes Datum die primäre ID festgelegt ist. ID klingt einfacher –

+0

Hey, es hat funktioniert !!! Ich habe "createdOn" in "id" geändert und presto! haha danke - Heres der Code, den ich in PHP verwendet: mysql_query ("löschen x von my_table x my_table z auf x.subscriberEmail = z.subscriberEmail wo x.id> z.id join") oder sterben (mysql_error ()); –

+0

Können Sie erklären, wie dieser Code in Englisch lesen - Es hilft logisch in der Lage sein, etwas zu lesen, um die Syntax zu verstehen - auch jetzt, wie verhindere ich Duplikate in erster Linie? Ich benutze bereits IGNORE einfügen, aber es ignoriert nicht –

0

Wenn Sie eine eindeutige ID für jede Zeile haben, können Sie so etwas versuchen. Frag mich nicht, warum genau du die zweite select-Anweisung brauchst, mysql lässt mich sonst nicht ausführen. Gruppieren Sie auch nach Spalten, die Ihre Ergebnisse einzigartig machen.

delete from my_table where id in (
    select id from (
    select id from my_table a group by subscriberEmail having count(*) > 1 
) b 
); 
+1

Ich glaube, das würde alle löschen, nicht nur die Extras. – Fosco

+0

Nein, würde es nicht. Die Gruppe nach gruppiert wie Zeilen nach SubscriberEmail. Also wird ein Abonnent mit mehr als 1 E-Mail ausgewählt (mit count (*)> 1). An dieser Stelle haben Sie ziemlich genau einen Rekordsatz von Abonnenten mit mehr als 1 E-Mail. Nimm die ID aus diesem Datensatz und lösche sie. Ich habe es versucht und es funktioniert wie ein Zauber. –

+0

Ausführen dieses Codes erzeugt Fehler „# 1064 - Sie haben einen Fehler in der SQL-Syntax, kontrollieren das Handbuch, die für die richtige Syntax zu Ihrem MySQL-Server-Version entspricht in der Nähe zu verwenden‚‘in Zeile 2“ - Code unten –

1

Wie wäre es damit, Sie müssen jetzt keine temporäre Tabellen erstellen selbst Joins

DELETE u1 FROM users u1, users u2 WHERE u1.id < u2.id AND u1.email = u2.email 

Um zu überprüfen, ob es irgendwelche doppelte Datensätze in der Tabelle sind

SELECT count(*) as Count, email FROM users u group by email having Count > 1 
Verwandte Themen