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

6 Möglichkeiten zum Auswählen doppelter Zeilen in Oracle

Die folgenden Beispiele geben doppelte Zeilen aus einer Oracle-Datenbanktabelle zurück.

Beispieldaten

Angenommen, wir haben eine Tabelle mit den folgenden Daten:

SELECT * FROM Pets;

Ergebnis:

PetId  PetName  PetType
-----  -------  -------
1      Wag      Dog    
1      Wag      Dog    
2      Scratch  Cat    
3      Tweet    Bird   
4      Bark     Dog    
4      Bark     Dog    
4      Bark     Dog    

Die ersten beiden Zeilen sind Duplikate, ebenso wie die letzten drei Zeilen. In diesem Fall enthalten die doppelten Zeilen doppelte Werte in allen Spalten, einschließlich der ID-Spalte.

Option 1

Wir können die folgende Abfrage verwenden, um zu sehen, wie viele Zeilen Duplikate sind:

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
ORDER BY PetId;

Ergebnis:

PETID	PETNAME	PETTYPE	Count
1	Wag	Dog	2
2	Scratch	Cat	1
3	Tweet	Bird	1
4	Bark	Dog	3

Wir haben die Zeilen nach allen Spalten gruppiert und die Zeilenanzahl jeder Gruppe zurückgegeben. Jede Zeile mit einer Anzahl größer als 1 ist ein Duplikat.

Wir können es nach Anzahl in absteigender Reihenfolge sortieren, sodass die Zeilen mit den meisten Duplikaten zuerst erscheinen:

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
ORDER BY Count(*) DESC;

Ergebnis:

PETID	PETNAME	PETTYPE	Count
4	Bark	Dog	3
1	Wag	Dog	2
2	Scratch	Cat	1
3	Tweet	Bird	1

Option 2

Wenn nur die doppelten Zeilen aufgelistet werden sollen, können wir den HAVING verwenden -Klausel, um nur Zeilen mit einer Anzahl größer als 1 zurückzugeben:

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
HAVING COUNT(*) > 1
ORDER BY COUNT(*) DESC;

Ergebnis:

PETID	PETNAME	PETTYPE	Count
4	Bark	Dog	3
1	Wag	Dog	2

Option 3

Eine weitere Option ist die Verwendung von ROW_NUMBER() Fensterfunktion:

SELECT 
    PetId,
    PetName,
    PetType,
    ROW_NUMBER() OVER ( 
        PARTITION BY PetId, PetName, PetType 
        ORDER BY PetId, PetName, PetType
        ) AS rn
FROM Pets;

Ergebnis:

PETID	PETNAME	PETTYPE	RN
1	Wag	Dog	1
1	Wag	Dog	2
2	Scratch	Cat	1
3	Tweet	Bird	1
4	Bark	Dog	1
4	Bark	Dog	2
4	Bark	Dog	3

Die PARTITION BY -Klausel teilt die von FROM erzeugte Ergebnismenge -Klausel in Partitionen, auf die die Funktion angewendet wird. Wenn wir Partitionen für die Ergebnismenge angeben, bewirkt jede Partition, dass die Nummerierung erneut beginnt (d. h. die Nummerierung beginnt bei 1 für die erste Zeile in jeder Partition).

Option 4

Wir können die obige Abfrage als allgemeinen Tabellenausdruck verwenden:

WITH cte AS 
    (
        SELECT 
            PetId,
            PetName,
            PetType,
            ROW_NUMBER() OVER ( 
                PARTITION BY PetId, PetName, PetType 
                ORDER BY PetId, PetName, PetType
                ) AS Row_Number
        FROM Pets
    )
SELECT * FROM cte WHERE Row_Number <> 1;

Ergebnis:

PETID	PETNAME	PETTYPE	ROW_NUMBER
1	Wag	Dog	2
4	Bark	Dog	2
4	Bark	Dog	3

Dadurch werden nur die überschüssigen Zeilen aus den übereinstimmenden Duplikaten zurückgegeben. Wenn also zwei identische Zeilen vorhanden sind, wird eine davon zurückgegeben. Wenn es drei identische Zeilen gibt, werden zwei zurückgegeben und so weiter.

Option 5

Da unsere Tabelle keine Primärschlüsselspalte enthält, können wir Oracles rowid nutzen Pseudospalte:

SELECT * FROM Pets
WHERE EXISTS (
  SELECT 1 FROM Pets p2 
  WHERE Pets.PetName = p2.PetName
  AND Pets.PetType = p2.PetType
  AND Pets.rowid > p2.rowid
);

Ergebnis:

PETID	PETNAME	PETTYPE
1	Wag	Dog
4	Bark	Dog
4	Bark	Dog

Das funktioniert so, dass jede Zeile in einer Oracle-Datenbank eine rowid hat 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. Beachten Sie jedoch, dass Zeilen in verschiedenen Tabellen, die zusammen im selben Cluster gespeichert sind, dieselbe rowid haben können .

Ein Vorteil des obigen Beispiels ist, dass wir SELECT * ersetzen können mit DELETE um die Tabelle zu deduplizieren.

Option 6

Und schließlich, hier ist eine weitere Option, die die rowid verwendet Pseudospalte:

SELECT * FROM Pets
WHERE rowid > (
  SELECT MIN(rowid) FROM Pets p2  
  WHERE Pets.PetName = p2.PetName
  AND Pets.PetType = p2.PetType
);

Ergebnis:

PETID	PETNAME	PETTYPE
1	Wag	Dog
4	Bark	Dog
4	Bark	Dog

Gleiches Ergebnis wie im vorherigen Beispiel.

Wie im vorherigen Beispiel können wir SELECT * ersetzen mit DELETE um doppelte Zeilen aus der Tabelle zu entfernen.