Zde je několik možností pro odstranění duplicitních řádků z tabulky v databázi Oracle, pokud tyto řádky mají sloupec primárního klíče nebo jedinečného identifikátoru.
V takových případech musí být primární klíč při porovnávání duplicitních řádků ignorován (kvůli skutečnosti, že primární klíče obsahují jedinečné hodnoty).
Ukázková data
Naše příklady používají následující data:
SELECT * FROM Dogs;
Výsledek:
DOGID | FIRSTNAME | LASTNAME |
---|---|---|
1 | Kůra | Smith |
2 | Kůra | Smith |
3 | Fuj | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
6 | Wag | Johnson |
7 | Wag | Johnson |
Vidíme, že první dva řádky jsou duplikáty, stejně jako poslední tři řádky.
DogId
sloupec obsahuje jedinečné hodnoty (protože je to primární klíč tabulky), ale při porovnávání duplikátů tento sloupec ignorujeme. Možná se často přistihnete, že potřebujete deduplikovat tabulky, které obsahují primární klíče, a proto k tomu lze použít následující příklady.
Možnost 1
Zde je naše první možnost, jak odstranit duplikáty výše uvedené tabulky:
DELETE FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
MINUS SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
SELECT * FROM Dogs;
Výsledek:
DOGID | FIRSTNAME | LASTNAME |
---|---|---|
1 | Kůra | Smith |
3 | Fuj | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Duplikáty byly odstraněny (ale jeden řádek z každého duplikátu zůstal).
Alternativně můžeme použít MAX()
místo funkce MIN()
funkce pro změnu, které řádky se mají odstranit.
Možnost 2
V tomto příkladu (a v následujících příkladech) budeme předpokládat, že tabulka byla obnovena do původního stavu (s duplikáty).
Zde je další příklad, který deduplikuje tabulku a poté vybere zbývající řádky:
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;
Výsledek:
DOGID | FIRSTNAME | LASTNAME |
---|---|---|
2 | Kůra | Smith |
3 | Fuj | Jones |
4 | Ruff | Robinson |
7 | Wag | Johnson |
Všimněte si, že jsem použil MAX()
funkce namísto MIN()
který jsem použil v předchozím příkladu. Vidíme, jaký to má vliv na operaci odstranění duplikace. Z tabulky byly odstraněny různé řádky.
Možnost 3
Zde je možnost, která nevyžaduje použití MIN()
nebo 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;
Výsledek:
DOGID | FIRSTNAME | LASTNAME |
---|---|---|
1 | Kůra | Smith |
3 | Fuj | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Možnost 4
Zde je další možnost:
DELETE FROM Dogs
WHERE DogId > (
SELECT MIN(DogId) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Výsledek:
DOGID | FIRSTNAME | LASTNAME |
---|---|---|
1 | Kůra | Smith |
3 | Fuj | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Možnost 5
Každý řádek v Oracle má rowid
pseudosloupec, který vrací adresu řádku. rowid
je jedinečný identifikátor pro řádky v tabulce a jeho hodnota obvykle jednoznačně identifikuje řádek v databázi (ačkoli je důležité si uvědomit, že řádky v různých tabulkách, které jsou uloženy společně ve stejném clusteru, mohou mít stejný rowid ).
Můžeme tedy použít rowid
v našem dotazu namísto DogId
sloupec:
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;
Výsledek:
DOGID | FIRSTNAME | LASTNAME |
---|---|---|
1 | Kůra | Smith |
3 | Fuj | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
I když se tento příklad může zdát poněkud nadbytečný, protože již máme sloupec primárního klíče, mohou nastat případy, kdy upřednostňujete použití rowid
. rowid
může být užitečné, pokud z nějakého důvodu nemůžete použít sloupec primárního klíče nebo pokud tabulka primární klíč nemá. Dokumentace Oracle také uvádí, že rowid
hodnoty jsou nejrychlejším způsobem přístupu k jednomu řádku.
Možnost 6
A zde je další příklad, ale s rowid
místo primárního klíče:
DELETE FROM Dogs
WHERE rowid > (
SELECT MIN(rowid) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Výsledek:
DOGID | FIRSTNAME | LASTNAME |
---|---|---|
1 | Kůra | Smith |
3 | Fuj | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |