Di seguito sono riportate alcune opzioni per eliminare le righe duplicate da una tabella in Oracle Database quando tali righe hanno una chiave primaria o una colonna identificatore univoco.
In questi casi, la chiave primaria deve essere ignorata quando si confrontano le righe duplicate (a causa del fatto che le chiavi primarie contengono valori univoci).
Dati campione
I nostri esempi utilizzano i seguenti dati:
SELECT * FROM Dogs;
Risultato:
DOGID | COGNOME | COGNOME |
---|---|---|
1 | Corteccia | Fabio |
2 | Corteccia | Fabio |
3 | Trama | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
6 | Wag | Johnson |
7 | Wag | Johnson |
Possiamo vedere che le prime due righe sono duplicate, così come le ultime tre righe.
Il DogId
la colonna contiene valori univoci (perché è la chiave primaria della tabella), ma stiamo ignorando quella colonna quando confrontiamo i duplicati. Potresti trovarti spesso a dover deduplicare le tabelle che contengono chiavi primarie, quindi i seguenti esempi possono essere utilizzati proprio per questo.
Opzione 1
Ecco la nostra prima opzione per deduplicare la tabella sopra:
DELETE FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
MINUS SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
SELECT * FROM Dogs;
Risultato:
DOGID | COGNOME | COGNOME |
---|---|---|
1 | Corteccia | Fabio |
3 | Trama | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
I duplicati sono stati rimossi (ma rimane una riga di ogni duplicato).
In alternativa possiamo usare il MAX()
funzione invece di MIN()
funzione per modificare le righe da eliminare.
Opzione 2
In questo esempio (e negli esempi seguenti) assumeremo che la tabella sia stata ripristinata allo stato originale (con i duplicati).
Ecco un altro esempio che deduplica la tabella e quindi seleziona le righe rimanenti:
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;
Risultato:
DOGID | COGNOME | COGNOME |
---|---|---|
2 | Corteccia | Fabio |
3 | Trama | Jones |
4 | Ruff | Robinson |
7 | Wag | Johnson |
Nota che ho usato MAX()
funzione invece di MIN()
che ho usato nell'esempio precedente. Possiamo vedere l'effetto che questo ha sull'operazione di de-duping. Ha cancellato diverse righe dalla tabella.
Opzione 3
Ecco un'opzione che non richiede l'uso di MIN()
o 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;
Risultato:
DOGID | COGNOME | COGNOME |
---|---|---|
1 | Corteccia | Fabio |
3 | Trama | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Opzione 4
Ecco un'altra opzione:
DELETE FROM Dogs
WHERE DogId > (
SELECT MIN(DogId) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Risultato:
DOGID | COGNOME | COGNOME |
---|---|---|
1 | Corteccia | Fabio |
3 | Trama | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Opzione 5
Ogni riga in Oracle ha un rowid
pseudocolonna che restituisce l'indirizzo della riga. Il rowid
è un identificatore univoco per le righe nella tabella e di solito il suo valore identifica in modo univoco una riga nel database (sebbene sia importante notare che righe in tabelle diverse che sono archiviate insieme nello stesso cluster possono avere lo stesso rowid
).
Possiamo quindi utilizzare il rowid
nella nostra query invece di DogId
colonna:
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;
Risultato:
DOGID | COGNOME | COGNOME |
---|---|---|
1 | Corteccia | Fabio |
3 | Trama | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Sebbene questo esempio possa sembrare leggermente superfluo, dato che abbiamo già una colonna di chiave primaria, potrebbero esserci casi in cui preferisci utilizzare il rowid
. Il rowid
può essere utile se per qualche motivo non è possibile utilizzare la colonna della chiave primaria o se la tabella non dispone di una chiave primaria. Inoltre, la documentazione di Oracle menziona che rowid
i valori sono il modo più veloce per accedere a una singola riga.
Opzione 6
Ed ecco l'altro esempio, ma con rowid
invece della chiave primaria:
DELETE FROM Dogs
WHERE rowid > (
SELECT MIN(rowid) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Risultato:
DOGID | COGNOME | COGNOME |
---|---|---|
1 | Corteccia | Fabio |
3 | Trama | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |