2016-07-13 5 views
1

Ich weiß, das Löschen von Duplikaten aus MySQL wird hier oft diskutiert. Aber keine der Lösungen funktioniert gut in meinem Fall.Löschen von Duplikaten aus großen MySQL Adresse DB

So habe ich eine DB mit Adressdaten fast wie folgt aus:

ID; Anrede; Vorname; Nachname; Strasse; Hausnummer; PLZ; Ort; Nummer_Art; Vorwahl; Rufnummer 

ID ist Primärschlüssel und einzigartig.

Und ich habe entrys zum Beispiel wie folgt aus:

1;Herr;Michael;Müller;Testweg;1;55555;Testhausen;Mobile;;67890 
2;Herr;Michael;Müller;Testweg;1;55555;Testhausen;Fixed;045678;877656 

Die verschiedenen Phone sind nicht das Problem, weil sie für mich nicht relevant sind. Also möchte ich nur die Duplikate in Nachname, Straße und Postleitzahl löschen. In diesem Fall ID 1 oder ID 2. Welche von beiden ist egal.

Ich habe versucht, es so eigentlich mit Lösch:

DELETE db 

FROM Import_Daten db, 
    Import_Daten dbl 

WHERE db.id > dbl.id AND 
     db.Lastname = dbl.Lastname AND 
     db.Strasse = dbl.Strasse AND 
     db.PLZ = dbl.PLZ; 

und eine Kopie Tabelle einfügen in:

INSERT INTO Import_Daten_1 

SELECT MIN(db.id), 
     db.Anrede, 
     db.Firstname, 
     db.Lastname, 
     db.Branche, 
     db.Strasse, 
     db.Hausnummer, 
     db.Ortsteil, 
     db.Land, 
     db.PLZ, 
     db.Ort, 
     db.Kontaktart, 
     db.Vorwahl, 
     db.Durchwahl 

FROM Import_Daten db, 
     Import_Daten dbl 

WHERE db.lastname = dbl.lastname AND 
     db.Strasse = dbl.Strasse And 
     db.PLZ = dbl.PLZ; 

Die vollständige Tabelle über 10Mio Zeilen enthält. Die Größe ist eigentlich mein Problem. Die mysql läuft auf einem MAMP Server auf einem Macbook mit 1,5GHZ und 4GB RAM. Also nicht wirklich schnell. SQL-Anweisungen werden in einem phpmyadmin ausgeführt. Eigentlich habe ich keine anderen Systemmöglichkeiten.

Antwort

0

Sie können eine neue Spalte z. uq und machen es UNIQUE.

ALTER TABLE Import_Daten 
ADD COLUMN `uq` BINARY(16) NULL, 
ADD UNIQUE INDEX `uq_UNIQUE` (`uq` ASC); 

Wenn dies geschehen ist Ihnen eine UPDATE Abfrage wie diese

ausführen kann
UPDATE IGNORE Import_Daten 
SET 
    uq = UNHEX(
      MD5(
      CONCAT(
       Import_Daten.Lastname, 
       Import_Daten.Street, 
       Import_Daten.Zipcode 
      ) 
      ) 
     ) 
WHERE 
    uq IS NULL; 

Sobald alle Einträge aktualisiert und die Abfrage erneut ausgeführt wird, werden alle Duplikate haben die uq Feld mit einem Wert = NULL und kann entfernt werden.

Das Ergebnis ist dann:

0 row(s) affected, 1 warning(s): 1062 Duplicate entry...

Für neu hinzugefügten Zeilen immer schaffen die uq Hash und und prüfen, mit dieser als Primärschlüssel, wenn alle Einträge eindeutig sind.

+0

Phantastisch! War wirklich schnell! Danke vielmals! – swapfile

+0

Um das Einfügen von Duplikaten zu verhindern, können wir einen eindeutigen Index für Felder (Feldname, Straße, PLZ) hinzufügen. – olegsv

+0

Wenn Sie diese Lösung zum ersten Mal anwenden, werden alle doppelten Datensätze gelöscht. Es wird keine Kopie des doppelten Datensatzes hinterlassen. – olegsv

1

Sie können eine stored procedure schreiben, die jedes Mal einen anderen Datenblock (z. B. rownumber zwischen zwei Werten) auswählt und nur aus diesem Bereich löscht. Auf diese Weise werden Sie schrittweise Ihre Duplikate löschen

+0

Dank. Ich habe keine Erfahrung mit gespeicherten Prozeduren. Ich werde es mir ansehen. Aber wenn j nur einen Bereich innerhalb der Zeilennummern "säubert" und die Daten nicht sortiert sind, kann es nicht funktionieren, oder? – swapfile

+0

@Chrisko - Link zu Dokumentation hinzugefügt –

1

Eine effektivere Zwei-Tabellen-Lösung kann wie folgt aussehen. Wir können nur die Daten speichern, die wir wirklich löschen müssen, und nur die Felder, die doppelte Informationen enthalten. Nehmen wir an, wir suchen nach doppelten Daten in den Feldern Nachname, Branche, Haushummer.

Tabelle Erstellen Sie die doppelten Daten

DROP TABLE data_to_delete;

Füllen Sie die Tabelle mit Daten, die wir löschen müssen, halten (ich nehme alle Felder VARCHAR (255) eintippen)

CREATE TABLE data_to_delete ( id BIGINT COMMENT 'this field will contain ID of row that we will not delete', cnt INT, Lastname VARCHAR(255), Branche VARCHAR(255), Hausnummer VARCHAR(255) ) AS SELECT min(t1.id) AS id, count(*) AS cnt, t1.Lastname, t1.Branche, t1.Hausnummer FROM Import_Daten AS t1 GROUP BY t1.Lastname, t1.Branche, t1.Hausnummer HAVING count(*)>1 ;

Jetzt löschen wir doppelte Daten und lassen nur einen Datensatz aller doppelten Sätze

übrig

DROP TABLE data_to_delete;

+0

Danke. Das funktioniert auch. Aber die Version von Bernhard ist viel schneller und besser für weitere Importe. – swapfile

+0

@Chrisko Ich stimme zu, es ist schneller. Um das Einfügen doppelter Datensätze zu verhindern, können Sie den eindeutigen Index verwenden. Außerdem habe ich Angst, diese Lösung auf vorhandene Daten anzuwenden, Sie werden ALLE doppelten Datensätze löschen und keine Kopie einer doppelten Folge hinterlassen. – olegsv

Verwandte Themen