Le seguenti query possono essere utilizzate per restituire righe duplicate in SQLite.
Qui, le righe duplicate contengono valori duplicati in tutte le colonne, inclusa la colonna ID.
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. Questo perché tutte e tre le colonne contengono gli stessi valori in ogni riga duplicata.
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
Qui abbiamo raggruppato le righe per tutte le colonne e restituito il conteggio delle righe di ciascun gruppo. Questo ci dice se una riga è unica (con un conteggio pari a 1) o duplicata (con un conteggio maggiore di 1).
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 PetId;
Risultato:
PetId PetName PetType Count ----- ------- ------- ----- 1 Wag Dog 2 4 Bark Dog 3
Opzione 3
Un'altra opzione è usare il ROW_NUMBER()
funzione finestra:
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS Row_Number
FROM Pets;
Risultato:
PetId PetName PetType Row_Number ----- ------- ------- ---------- 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
*,
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.
Questa query può essere utile per mostrare quante righe verranno rimosse dalla tabella in un'operazione di deduplicazione. In alcuni altri DBMS (almeno in SQL Server), possiamo sostituire l'ultimo SELECT *
con DELETE
per eliminare le righe duplicate dalla tabella. Ma SQLite non ci permetterà di aggiornare il CTE in questo modo.
Fortunatamente, le prossime due opzioni possono essere modificate per eseguire un'eliminazione.
Opzione 5
Possiamo sfruttare rowid
di SQLite :
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
Come funziona? Per impostazione predefinita, ogni riga in SQLite ha una colonna speciale, solitamente chiamata rowid
, che identifica in modo univoco quella riga all'interno della tabella. Questo può essere rimosso se necessario, ma a meno che non sia stato rimosso esplicitamente, sarai in grado di sfruttarlo all'interno delle tue query.
Opzione 6
E infine, ecco un'altra opzione che utilizza rowid
di SQLite :
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