Følgende eksempler returnerer dublerede rækker fra en Oracle-databasetabel.
Eksempeldata
Antag, at vi har en tabel med følgende data:
SELECT * FROM Pets;
Resultat:
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 første to rækker er dubletter, ligesom de sidste tre rækker. I dette tilfælde indeholder de duplikerede rækker dublerede værdier på tværs af alle kolonner, inklusive ID-kolonnen.
Valgmulighed 1
Vi kan bruge følgende forespørgsel til at se, hvor mange rækker der er dubletter:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY PetId;
Resultat:
PETID PETNAME PETTYPE Count 1 Wag Dog 2 2 Scratch Cat 1 3 Tweet Bird 1 4 Bark Dog 3
Vi grupperede rækkerne efter alle kolonner og returnerede rækkeantallet for hver gruppe. Enhver række med et antal større end 1 er en dublet.
Vi kan bestille det efter antal i faldende rækkefølge, så rækkerne med flest dubletter vises først:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY Count(*) DESC;
Resultat:
PETID PETNAME PETTYPE Count 4 Bark Dog 3 1 Wag Dog 2 2 Scratch Cat 1 3 Tweet Bird 1
Valgmulighed 2
Hvis vi kun vil have de duplikerede rækker på listen, kan vi bruge koden HAVING
klausul for kun at returnere rækker med et antal større end 1:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
HAVING COUNT(*) > 1
ORDER BY COUNT(*) DESC;
Resultat:
PETID PETNAME PETTYPE Count 4 Bark Dog 3 1 Wag Dog 2
Valgmulighed 3
En anden mulighed er at bruge ROW_NUMBER()
vinduesfunktion:
SELECT
PetId,
PetName,
PetType,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS rn
FROM Pets;
Resultat:
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
PARTITION BY
klausul deler resultatsættet produceret af FROM
klausul i partitioner, som funktionen anvendes på. Når vi angiver partitioner for resultatsættet, får hver partition nummereringen til at starte forfra (dvs. nummereringen starter ved 1 for den første række i hver partition).
Valgmulighed 4
Vi kan bruge ovenstående forespørgsel som et almindeligt tabeludtryk:
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;
Resultat:
PETID PETNAME PETTYPE ROW_NUMBER 1 Wag Dog 2 4 Bark Dog 2 4 Bark Dog 3
Dette returnerer kun de overskydende rækker fra de matchende dubletter. Så hvis der er to identiske rækker, returnerer den en af dem. Hvis der er tre ens rækker, returnerer det to, og så videre.
Valgmulighed 5
Da vores tabel ikke indeholder en primær nøglekolonne, kan vi drage fordel af Oracles rowid
pseudokolonne:
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
);
Resultat:
PETID PETNAME PETTYPE 1 Wag Dog 4 Bark Dog 4 Bark Dog
Sådan fungerer det, at hver række i en Oracle-database har en rowid
pseudokolonne, der returnerer adressen på rækken. rowid
er en unik identifikator for rækker i tabellen, og normalt identificerer dens værdi entydigt en række i databasen. Det er dog vigtigt at bemærke, at rækker i forskellige tabeller, der er gemt sammen i den samme klynge, kan have den samme rowid
.
En fordel ved ovenstående eksempel er, at vi kan erstatte SELECT *
med DELETE
for at de-dupere bordet.
Valgmulighed 6
Og endelig, her er en anden mulighed, der bruger rowid
pseudokolonne:
SELECT * FROM Pets
WHERE rowid > (
SELECT MIN(rowid) FROM Pets p2
WHERE Pets.PetName = p2.PetName
AND Pets.PetType = p2.PetType
);
Resultat:
PETID PETNAME PETTYPE 1 Wag Dog 4 Bark Dog 4 Bark Dog
Samme resultat som det foregående eksempel.
Som med det foregående eksempel kan vi erstatte SELECT *
med DELETE
for at fjerne duplikerede rækker fra tabellen.