Oracle
 sql >> Datenbank >  >> RDS >> Oracle

6 Möglichkeiten zum Löschen doppelter Zeilen mit einem Primärschlüssel in Oracle

Hier sind einige Optionen zum Löschen doppelter Zeilen aus einer Tabelle in Oracle Database, wenn diese Zeilen einen Primärschlüssel oder eine eindeutige Kennungsspalte haben.

In solchen Fällen muss der Primärschlüssel beim Vergleich doppelter Zeilen ignoriert werden (aufgrund der Tatsache, dass Primärschlüssel eindeutige Werte enthalten).

Beispieldaten

Unsere Beispiele verwenden die folgenden Daten:

SELECT * FROM Dogs;

Ergebnis:

HUNDID VORNAME NACHNAME
1 Rillen Smith
2 Rillen Smith
3 Wuff Jones
4 Ruff Robinson
5 Wag Johnson
6 Wag Johnson
7 Wag Johnson

Wir können sehen, dass die ersten beiden Zeilen Duplikate sind, ebenso wie die letzten drei Zeilen.

Die DogId -Spalte enthält eindeutige Werte (weil es der Primärschlüssel der Tabelle ist), aber wir ignorieren diese Spalte beim Vergleichen von Duplikaten. Möglicherweise müssen Sie Tabellen, die Primärschlüssel enthalten, häufig deduplizieren, und daher können die folgenden Beispiele verwendet werden, um genau das zu tun.

Option 1

Hier ist unsere erste Option zum Deduplizieren der obigen Tabelle:

DELETE FROM Dogs 
WHERE DogId IN (
    SELECT DogId FROM Dogs 
    MINUS SELECT MIN(DogId) FROM Dogs 
    GROUP BY FirstName, LastName
    );

SELECT * FROM Dogs;

Ergebnis:

HUNDID VORNAME NACHNAME
1 Rillen Smith
3 Wuff Jones
4 Ruff Robinson
5 Wag Johnson

Die Duplikate wurden entfernt (aber eine Zeile jedes Duplikats bleibt).

Wir können alternativ den MAX() verwenden anstelle von MIN() Funktion, um zu ändern, welche Zeilen gelöscht werden.

Option 2

In diesem Beispiel (und den folgenden Beispielen) gehen wir davon aus, dass die Tabelle in ihrem ursprünglichen Zustand (mit den Duplikaten) wiederhergestellt wurde.

Hier ist ein weiteres Beispiel, das die Tabelle dedupliziert und dann die verbleibenden Zeilen auswählt:

DELETE FROM Dogs WHERE DogId IN (
    SELECT d2.DogId 
    FROM Dogs d1, Dogs d2 
    WHERE d1.FirstName = d2.FirstName 
    AND d1.LastName = d2.LastName 
    AND d1.DogId <> d2.DogId 
    AND d1.DogId=( 
        SELECT MAX(DogId) 
        FROM Dogs d3 
        WHERE d3.FirstName = d1.FirstName 
        AND d3.LastName = d1.LastName
    )
);

SELECT * FROM Dogs;

Ergebnis:

HUNDID VORNAME NACHNAME
2 Rillen Smith
3 Wuff Jones
4 Ruff Robinson
7 Wag Johnson

Beachten Sie, dass ich MAX() verwendet habe Funktion anstelle von MIN() die ich im vorherigen Beispiel verwendet habe. Wir können die Auswirkungen sehen, die dies auf den Deduplizierungsvorgang hat. Es löschte verschiedene Zeilen aus der Tabelle.

Option 3

Hier ist eine Option, die keine Verwendung von MIN() erfordert oder MAX() :

DELETE FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.DogId > d2.DogId
);

SELECT * FROM Dogs;

Ergebnis:

HUNDID VORNAME NACHNAME
1 Rillen Smith
3 Wuff Jones
4 Ruff Robinson
5 Wag Johnson

Option 4

Hier ist eine weitere Option:

DELETE FROM Dogs
WHERE DogId > (
  SELECT MIN(DogId) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
);

SELECT * FROM Dogs;

Ergebnis:

HUNDID VORNAME NACHNAME
1 Rillen Smith
3 Wuff Jones
4 Ruff Robinson
5 Wag Johnson

Option 5

Jede Zeile in Oracle hat eine rowid Pseudospalte, die die Adresse der Zeile zurückgibt. Die rowid ist ein eindeutiger Bezeichner für Zeilen in der Tabelle, und normalerweise identifiziert sein Wert eine Zeile in der Datenbank eindeutig (obwohl es wichtig ist zu beachten, dass Zeilen in verschiedenen Tabellen, die zusammen im selben Cluster gespeichert sind, dieselbe rowid ).

Wir können daher die rowid verwenden in unserer Abfrage anstelle der DogId Spalte:

DELETE FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.rowid > d2.rowid
);

SELECT * FROM Dogs;

Ergebnis:

HUNDID VORNAME NACHNAME
1 Rillen Smith
3 Wuff Jones
4 Ruff Robinson
5 Wag Johnson

Obwohl dieses Beispiel etwas überflüssig erscheinen mag, da wir bereits eine Primärschlüsselspalte haben, kann es Fälle geben, in denen Sie die rowid bevorzugen . Die rowid kann nützlich sein, wenn Sie die Primärschlüsselspalte aus irgendeinem Grund nicht verwenden können oder wenn die Tabelle keinen Primärschlüssel hat. Außerdem erwähnt die Dokumentation von Oracle diese rowid Werte sind der schnellste Weg, um auf eine einzelne Zeile zuzugreifen.

Option 6

Und hier ist das andere Beispiel, aber mit rowid anstelle des Primärschlüssels:

DELETE FROM Dogs
WHERE rowid > (
  SELECT MIN(rowid) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
);

SELECT * FROM Dogs;

Ergebnis:

HUNDID VORNAME NACHNAME
1 Rillen Smith
3 Wuff Jones
4 Ruff Robinson
5 Wag Johnson