Oracle
 sql >> Database >  >> RDS >> Oracle

6 modi per selezionare righe duplicate in Oracle

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.