Jörg Menker

Öfter als einem lieb ist steht man vor dem Dublettenproblem, bei dem (meist fälschlicherweise) der gleiche Datensatz mehrfach in einer Tabelle auftaucht. Wenn man nicht die komplette Tabelle löschen und neu laden will oder kann, müssen die Dubletten auf andere Art und Weise eliminiert werden. Im Falle einer Tabelle mit einem Primärschlüssel (PK) unterscheiden sich die doppelt oder mehrfach vorhandenen Datensätze durch einen unterschiedlichen PK, ansonsten nicht. Das ist ein guter Ansatz um die Dubletten los zu werden nach der Mimik Self-Join auf alle Spalten außer dem PK und unterschiedlicher PK, aber es gibt auch noch andere Möglichkeiten wie wir sehen werden.

Zur Verdeutlichung erstellen wir ein kleines Beispiel:

In die erstellte Beispieltabelle stellen wir jetzt ein paar Datensätze mit Dubletten ein:

Ein SELECT * FROM [SIMULACRUM].[dbo].[dubtab1] order by tab_bk ergibt folgendes erwartungskonformes Ergebnis:

dubletten_pk_1

Wie man sieht ist jeder Datensatz doppelt vorhanden bis auf tab_bk = ‚005‘, der sogar dreifach vorhanden ist, und unterscheidet sich nur durch den unterschiedlichen PK (tab_id).

Eine Möglichkeit die Dubletten zu löschen besteht in der Verwendung des Merge-Befehls:

Im inneren Select-Statement verwenden wir einen Self-Join über alle Spalten und prüfen auf Gleichheit. Von den so gefundenen Datensätzen wird nur der größere Wert für den PK (tab_id) verwendet.

dubletten_pk_2

Als Ergebnis erhält man eine Tabelle ohne Dubletten:

dubletten_pk_3

Alternativ kann man dieses Szenario auch mit einem Anti-Join angehen:

Einfacher wäre es, wenn T-SQL die Verwendung eines Tabellenalias im Delete-Zweig zulassen würde, aber auch so erhalten wir das gewünschte Ergebnis.

 

Ein wenig anders sieht die Sache aus, wenn die Tabelle, die die Dubletten enthält, keinen Primärschlüssel aufweist. Auch hierzu schnell ein kleines Beispiel:

Und auch hier stellen wir die gleichen Datensätze ein (wenn man einmal vom fehlenden PK absieht):

Ein select * from SIMULACRUM.dbo.dubtab2 order by tab_bk ergibt folgendes Ergebnis:

dubletten_opk_1

Auch hier sind alle Datensätze mindestens doppelt vorhanden, die Datensätze mit tab_bK = ‚005‘ sogar dreifach.

Für die Dubletteneliminierung verwenden wir jetzt eine Common Table Expression (CTE):

Wieder ergibt sich das gewünschte dublettenfreie Ergebnis:

dubletten_opk_2

Diese Art der Dubletteneliminierung ist eleganter als das erste Verfahren unter Verwendung eines Merge-Befehls und lässt sich genauso gut auch für das erste Beispiel verwenden. Streng genommen müsste man aber die partition-by-clause noch um die übrigen Nicht-Schlüsselfelder erweitern um mit Sicherheit in allen Spalten doppelt vorhandene Sätze zu eliminieren. So wie die CTE jetzt formuliert ist, eliminiert sie Sätze schon dann, wenn nur die Spalte tab_bk mehrfach vorhanden ist.

Mit dem gleichem Thema angewendet auf sehr große Tabellen befasst sich auch der Beitrag meines Kollegen Hilmar Buchta.