De volgende voorbeelden retourneren dubbele rijen uit een Oracle Database-tabel.
Voorbeeldgegevens
Stel dat we een tabel hebben met de volgende gegevens:
SELECT * FROM Pets;
Resultaat:
PetId PetName PetType ----- ------- ------- 1 Wag Dog 1 Wag Dog 2 Scratch Cat 3 Tweet Bird 4 Bark Dog 4 Bark Dog 4 Bark Dog
De eerste twee rijen zijn duplicaten, evenals de laatste drie rijen. In dit geval bevatten de dubbele rijen dubbele waarden in alle kolommen, inclusief de ID-kolom.
Optie 1
We kunnen de volgende query gebruiken om te zien hoeveel rijen duplicaten zijn:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY PetId;
Resultaat:
PETID PETNAME PETTYPE Count 1 Wag Dog 2 2 Scratch Cat 1 3 Tweet Bird 1 4 Bark Dog 3
We hebben de rijen op alle kolommen gegroepeerd en het aantal rijen van elke groep geretourneerd. Elke rij met een telling groter dan 1 is een duplicaat.
We kunnen het sorteren op telling in aflopende volgorde, zodat de rijen met de meeste duplicaten eerst verschijnen:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY Count(*) DESC;
Resultaat:
PETID PETNAME PETTYPE Count 4 Bark Dog 3 1 Wag Dog 2 2 Scratch Cat 1 3 Tweet Bird 1
Optie 2
Als we alleen de dubbele rijen willen vermelden, kunnen we de HAVING
. gebruiken clausule om alleen rijen te retourneren met een telling groter dan 1:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
HAVING COUNT(*) > 1
ORDER BY COUNT(*) DESC;
Resultaat:
PETID PETNAME PETTYPE Count 4 Bark Dog 3 1 Wag Dog 2
Optie 3
Een andere optie is om de ROW_NUMBER()
. te gebruiken vensterfunctie:
SELECT
PetId,
PetName,
PetType,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS rn
FROM Pets;
Resultaat:
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
De PARTITION BY
clausule verdeelt de resultaatset geproduceerd door de FROM
clausule in partities waarop de functie wordt toegepast. Wanneer we partities specificeren voor de resultatenset, zorgt elke partitie ervoor dat de nummering opnieuw begint (d.w.z. de nummering begint bij 1 voor de eerste rij in elke partitie).
Optie 4
We kunnen de bovenstaande query gebruiken als een algemene tabeluitdrukking:
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;
Resultaat:
PETID PETNAME PETTYPE ROW_NUMBER 1 Wag Dog 2 4 Bark Dog 2 4 Bark Dog 3
Dit retourneert alleen de overtollige rijen van de overeenkomende duplicaten. Dus als er twee identieke rijen zijn, wordt er één geretourneerd. Als er drie identieke rijen zijn, worden er twee geretourneerd, enzovoort.
Optie 5
Aangezien onze tabel geen primaire sleutelkolom bevat, kunnen we profiteren van Oracle's rowid
pseudokolom:
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
);
Resultaat:
PETID PETNAME PETTYPE 1 Wag Dog 4 Bark Dog 4 Bark Dog
Zoals dit werkt, heeft elke rij in een Oracle-database een rowid
pseudokolom die het adres van de rij retourneert. De rowid
is een unieke id voor rijen in de tabel, en gewoonlijk identificeert de waarde ervan op unieke wijze een rij in de database. Het is echter belangrijk op te merken dat rijen in verschillende tabellen die samen in hetzelfde cluster zijn opgeslagen, dezelfde rowid
kunnen hebben. .
Een voordeel van het bovenstaande voorbeeld is dat we SELECT *
. kunnen vervangen met DELETE
om de tabel te ontdubbelen.
Optie 6
En tot slot, hier is nog een optie die de rowid
. gebruikt pseudokolom:
SELECT * FROM Pets
WHERE rowid > (
SELECT MIN(rowid) FROM Pets p2
WHERE Pets.PetName = p2.PetName
AND Pets.PetType = p2.PetType
);
Resultaat:
PETID PETNAME PETTYPE 1 Wag Dog 4 Bark Dog 4 Bark Dog
Hetzelfde resultaat als het vorige voorbeeld.
Net als bij het vorige voorbeeld kunnen we SELECT *
. vervangen met DELETE
om dubbele rijen uit de tabel te verwijderen.