Följande exempel returnerar dubbletter av rader från en Oracle Database-tabell.
Exempeldata
Anta att vi har en tabell med följande 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 två första raderna är dubbletter, liksom de tre sista raderna. I det här fallet innehåller dubblettraderna dubblettvärden över alla kolumner, inklusive ID-kolumnen.
Alternativ 1
Vi kan använda följande fråga för att se hur många rader som är dubbletter:
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 grupperade raderna efter alla kolumner och returnerade radantalet för varje grupp. Varje rad med ett antal större än 1 är en dubblett.
Vi kan sortera efter antal i fallande ordning, så att raderna med flest dubbletter visas 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
Alternativ 2
Om vi bara vill ha dubblettraderna listade kan vi använda koden HAVING
sats för att endast returnera rader med ett antal större än 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
Alternativ 3
Ett annat alternativ är att använda ROW_NUMBER()
fönsterfunktion:
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
satsen delar resultatuppsättningen som produceras av FROM
sats i partitioner som funktionen tillämpas på. När vi anger partitioner för resultatuppsättningen, gör varje partition att numreringen börjar om igen (dvs. numreringen börjar på 1 för den första raden i varje partition).
Alternativ 4
Vi kan använda ovanstående fråga som ett vanligt tabelluttryck:
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
Detta returnerar bara överflödiga rader från matchande dubbletter. Så om det finns två identiska rader returneras en av dem. Om det finns tre identiska rader returneras två, och så vidare.
Alternativ 5
Eftersom vår tabell inte innehåller en primärnyckelkolumn kan vi dra fördel av Oracles rowid
pseudokolumn:
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å här fungerar det är att varje rad i en Oracle-databas har en rowid
pseudokolumn som returnerar adressen till raden. rowid
är en unik identifierare för rader i tabellen, och vanligtvis identifierar dess värde unikt en rad i databasen. Det är dock viktigt att notera att rader i olika tabeller som är lagrade tillsammans i samma kluster kan ha samma rowid
.
En fördel med exemplet ovan är att vi kan ersätta SELECT *
med DELETE
för att de-dupera tabellen.
Alternativ 6
Och slutligen, här är ett annat alternativ som använder rowid
pseudokolumn:
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
Samma resultat som föregående exempel.
Som med föregående exempel kan vi ersätta SELECT *
med DELETE
för att ta bort dubbletter av rader från tabellen.