Gli esempi seguenti restituiscono righe duplicate da una tabella Oracle Database.
Dati campione
Supponiamo di avere una tabella con i seguenti dati:
SELECT * FROM Pets;
Risultato:
PetId PetName PetType ----- ------- ------- 1 Wag Dog 1 Wag Dog 2 Scratch Cat 3 Tweet Bird 4 Bark Dog 4 Bark Dog 4 Bark Dog
Le prime due righe sono duplicate, così come le ultime tre righe. In questo caso le righe duplicate contengono valori duplicati in tutte le colonne, inclusa la colonna ID.
Opzione 1
Possiamo usare la seguente query per vedere quante righe sono duplicate:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY PetId;
Risultato:
PETID PETNAME PETTYPE Count 1 Wag Dog 2 2 Scratch Cat 1 3 Tweet Bird 1 4 Bark Dog 3
Abbiamo raggruppato le righe in base a tutte le colonne e restituito il conteggio delle righe di ciascun gruppo. Qualsiasi riga con un conteggio maggiore di 1 è un duplicato.
Possiamo ordinarlo per conteggio in ordine decrescente, in modo che le righe con il maggior numero di duplicati appaiano per prime:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY Count(*) DESC;
Risultato:
PETID PETNAME PETTYPE Count 4 Bark Dog 3 1 Wag Dog 2 2 Scratch Cat 1 3 Tweet Bird 1
Opzione 2
Se vogliamo solo le righe duplicate elencate, possiamo usare il HAVING
clausola per restituire solo le righe con un conteggio maggiore di 1:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
HAVING COUNT(*) > 1
ORDER BY COUNT(*) DESC;
Risultato:
PETID PETNAME PETTYPE Count 4 Bark Dog 3 1 Wag Dog 2
Opzione 3
Un'altra opzione è usare il ROW_NUMBER()
funzione finestra:
SELECT
PetId,
PetName,
PetType,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS rn
FROM Pets;
Risultato:
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
Il PARTITION BY
La clausola divide il set di risultati prodotto dal FROM
clausola in partizioni a cui viene applicata la funzione. Quando specifichiamo le partizioni per il set di risultati, ogni partizione fa ricominciare la numerazione (cioè la numerazione inizierà da 1 per la prima riga in ogni partizione).
Opzione 4
Possiamo usare la query precedente come un'espressione di tabella comune:
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;
Risultato:
PETID PETNAME PETTYPE ROW_NUMBER 1 Wag Dog 2 4 Bark Dog 2 4 Bark Dog 3
Questo restituisce solo le righe in eccesso dai duplicati corrispondenti. Quindi se ci sono due righe identiche, ne restituisce una. Se sono presenti tre righe identiche, ne restituisce due e così via.
Opzione 5
Dato che la nostra tabella non contiene una colonna di chiave primaria, possiamo sfruttare rowid
di Oracle pseudocolonna:
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
);
Risultato:
PETID PETNAME PETTYPE 1 Wag Dog 4 Bark Dog 4 Bark Dog
Il modo in cui funziona è che ogni riga in un database Oracle ha un rowid
pseudocolonna che restituisce l'indirizzo della riga. Il rowid
è un identificatore univoco per le righe nella tabella e in genere il suo valore identifica in modo univoco una riga nel database. Tuttavia, è importante notare che le righe di tabelle diverse archiviate insieme nello stesso cluster possono avere lo stesso rowid
.
Un vantaggio dell'esempio sopra è che possiamo sostituire SELECT *
con DELETE
per deduplicare il tavolo.
Opzione 6
E infine, ecco un'altra opzione che utilizza il rowid
pseudocolonna:
SELECT * FROM Pets
WHERE rowid > (
SELECT MIN(rowid) FROM Pets p2
WHERE Pets.PetName = p2.PetName
AND Pets.PetType = p2.PetType
);
Risultato:
PETID PETNAME PETTYPE 1 Wag Dog 4 Bark Dog 4 Bark Dog
Stesso risultato dell'esempio precedente.
Come nell'esempio precedente, possiamo sostituire SELECT *
con DELETE
per rimuovere le righe duplicate dalla tabella.