Apr 292011
 

Diese Aufgabe treffe ich immer wieder an. Ich habe eine Datenbank mit etlichen Tabellen und irgend aus einem Grund enthält eine Tabelle doppelte Einträge. Doppelte Einträge heisst in dem Fall, dass Records bis auf ein paar bestimmte Felder gleich sind. Diese sollen nun gelöscht werden.

Wenn im Internet nach einer Lösung gesucht wird finden sich etliche Lösungen. 95% davon nutzen aber eine Temporäre Tabelle, und das will ich nicht. Ich will alles mit einem einzigen Query löschen.

Wie das gemacht werden kann will ich nun kurz Zeigen. Um Daten zu haben, die gelöscht werden können, habe ich die Tabelle be_Posts von BlogEngine.NET ein wenig angepasst und 200 Doppelte Postings generiert. Naiverweise gehe ich davon aus das keine Beziehungen zu anderen Tabellen bestehen. Das soll uns zum jetzigen Zeitpunkt nicht interessieren.

Schritt 1 – Finden der doppelten Einträge

Zuerst muss bestimmt werden ob es überhaupt doppelte Einträge gibt. Dazu muss man nicht alle Felder der Tabelle heranziehen. Es reicht ein paar Felder zu bestimmen die einen Eintrag als doppelt kennzeichnen. Diese Felder werden gruppiert und es wird gezählt wie viele Einträge die Gruppe hat. Bei den Postings habe ich jetzt mal bestimmt das ein Posting eindeutig ist wenn es den selben “Title”, “PostContent” und das selbe “DateCreated” hat. Beim Datum muss man allerdings vorsichtig sein. Je nach dem wie der doppelte Eintrag entstanden ist können hier Sekundenbruchteile Diverenzen vorhanden sein und schon ist der Datensatz nicht mehr gleich. Auch das “Rating” Feld nehme ich nicht rein. Es könnte ja gut sein das ein Posting der Doublette schon bewertet wurde. Man muss also gut überlegen anhand welcher Felder ein Record als identisch gekennzeichnet wird.

Schritt 2 – Ermitteln der ID’s die gelöscht werden können

Jetzt ist zwar bekannte welche Datensätze doppelt in der Tabelle sind. Aber es ist noch nicht bekannt welchen man genau löschen darf. Von den doppelten Einträgen darf ja nur einer gelöscht werden. Um nun die passenden ID’s zu finden geht man wie folgt vor.

Zuerst wird eine neue View erstellt worin die Tabelle der Posts ist. Dann wird in der View eine “Neue abgeleitet Tabelle hinzufügen” hinzugefügt. In den lehren Rumpf kopiert man das Query von Schritt 1. Danach wird noch ein Join auf die drei Felder gemacht und die “PostID” ausgegeben. Damit aber nur eine ID pro doppelten Eintrag kommt muss die ganze Geschichte noch gruppiert werden. Auf das Feld “PostID” setzt man im Feld “Gruppieren nach” die Funktion “Min”. Somit wird pro Doublette nur eine ID zurückgegeben. Beim Ausführen der Abfrage wird aber noch ein Fehler geworfen. Auf einem Feld vom Typ “uniqueidentifier” kann kein “Min” angewendet werden. Daher bediene ich mich eines CAST und mache ein VARCHAR(40) daraus. Zu sehen in der Zeile 1.

Das sieht dann in etwa so aus.

Query im Designer

PostID ist nicht selektiert, da ein MIN(CAST(… auf dem Feld ist.

Wenn diese Abfrage ausgeführt wird kommen 200 Records zurück. Wir haben ja 200 Doubletten in der Tabelle.

Ab Zeile 3 sieht man sehr schon das Query von Schritt 1.

Schritt 3 – Löschen der doppelten Einträge

Jetzt ist man im Besitz aller nötigen Daten um die Doubletten zu löschen. Es ist bekannt was genau doppelt ist und es ist die ID bekannt. Wir haben also 200 Records die gelöscht werden müssen.

Also wird einfach ein “DELETE FROM be_Posts WHERE (PostID IN (…” gemacht. Das sieht das so aus.

Wenn diese Abfrage nun ausgeführt wird sollte folgende Meldung kommen: (200 Zeile(n) betroffen)

Ergebnis des DELETE Querys

 

Wie man nun sieht kann das löschen von Doubletten mit einer einzigen Abfrage gemacht werden. Es muss nur bekannt sein was genau gelöscht werden muss. Ich hoffe das hilft dem Einen oder Anderen.

Wenn es noch einfacher gehen sollte lasst es mich wissen.

Anmerkungen

Wenn das jemand nachmachen will, mit der be_Posts von BlogEngine.NET wird er beim Schritt 3 enttäuscht. Es wird ein Fehler geworfen da die Tabelle noch Abhängigkeiten vorweist. Ich habe die für den Test einfach gelöscht. Aber in Wirklichkeit müsste man diese natürlich berücksichtigen.

  2 Responses to “Doppelte Einträge in einer Tabelle mit einem SQL Query löschen”

Comments (2)
  1. Super Anleitung! Hat gut funktioniert. Nur bei mehr als 2 Dubletten muss die Anweisung öfters gestartet werden bis 0 Zeilen mehr betroffen sind.

    Gruss

  2. Hallo
    Danke für das Feedback. Das mit den mehr als zwei Dubletten war mir gar nicht bewusst. Mal schauen ob ich mir das noch anschaue.

Sorry, the comment form is closed at this time.