Trovare i duplicati in SQL può essere un compito noioso, ma è una competenza essenziale per chiunque lavori con i database. I duplicati possono causare errori, discrepanze e incoerenze nei dati, portando a risultati errati e prestazioni scadenti. Pertanto, è fondamentale identificare e rimuovere i duplicati dalle tabelle per garantire l’integrità e l’accuratezza dei dati.
SQL fornisce diversi modi per trovare i duplicati nei dati, a seconda delle esigenze e della struttura delle tabelle. È possibile utilizzare le clausole GROUP BY e HAVING per raggruppare i record per una particolare colonna e filtrare i duplicati in base a un conteggio o condizione. In alternativa, è possibile utilizzare la parola chiave DISTINCT per selezionare solo i valori univoci e confrontarli con la tabella originale per identificare i duplicati. Esistono anche funzioni e operatori specializzati, come COUNT(), EXISTS e JOIN, che possono aiutare a trovare i duplicati in scenari più complessi.
In questa guida troverai esercizi SQL interattivi che ti permettono di praticare la ricerca di duplicati nel tuo browser — senza necessità di configurare un database. Scrivi query, ricevi feedback immediato e verifica se i tuoi risultati corrispondono all’output atteso.
In questo articolo, esploreremo varie tecniche per trovare i duplicati in SQL, dalle query semplici ai metodi avanzati, e forniremo esempi e best practice per aiutarti a padroneggiare questa competenza. Che tu sia un principiante o uno sviluppatore SQL esperto, questa guida ti aiuterà a migliorare la qualità e l’efficienza dei tuoi dati rilevando ed eliminando i duplicati dalle tabelle. Per praticare queste query, considera l’uso di un editor SQL moderno come l’editor SQL di Beekeeper Studio, che offre evidenziazione della sintassi e funzionalità di completamento automatico.
Trovare i Duplicati Usando le Clausole GROUP BY e HAVING
Un modo per trovare valori duplicati in SQL è utilizzare le clausole GROUP BY e HAVING. Queste clausole permettono di raggruppare le righe che hanno gli stessi valori in una o più colonne e poi filtrare i gruppi in base a determinati criteri. Ecco come funziona:
- Inizia selezionando le colonne che vuoi controllare per i duplicati usando l’istruzione SELECT.
- Usa la clausola GROUP BY per raggruppare le righe per le colonne selezionate.
- Usa la funzione COUNT nella clausola HAVING per filtrare i gruppi che hanno più di una riga. Questi sono i gruppi che contengono duplicati.
Per esempio, supponiamo di avere una tabella chiamata “customers” con colonne per “name” e “email”. Vuoi trovare tutti i clienti che si sono registrati con lo stesso indirizzo email. Ecco come sarebbe la query SQL:
SELECT name, email, COUNT(*)
FROM customers
GROUP BY email
HAVING COUNT(*) > 1;
Questa query raggruppa i clienti per i loro indirizzi email e poi conta il numero di clienti in ogni gruppo. La clausola HAVING filtra i gruppi che hanno un solo cliente, lasciando solo i gruppi con indirizzi email duplicati.
Prova tu stesso:
[[ testData.title ]]
Interroga la tabella users per trovare tutti gli indirizzi email che compaiono più di una volta. Restituisci l’email e il count di quante volte ogni email duplicata compare.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Tabelle Disponibili
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
È importante notare che la clausola GROUP BY deve includere tutte le colonne che stai selezionando tranne quelle che usano una funzione aggregata come COUNT. Altrimenti, la query restituirà un errore.
Un’altra cosa da tenere a mente è che la funzione COUNT conta tutte le righe in ogni gruppo, non solo quelle uniche. Quindi se hai più righe con lo stesso nome e indirizzo email, saranno tutte contate come duplicati.
Oltre a usare le clausole GROUP BY e HAVING, puoi anche utilizzare altre istruzioni SQL come ORDER BY, WHERE e JOIN per affinare ulteriormente la ricerca di duplicati. Puoi anche usare vincoli univoci per impedire l’inserimento di valori duplicati in una tabella in primo luogo.
Nel complesso, trovare i duplicati in SQL può essere uno strumento potente per pulire dati non elaborati o identificare potenziali errori umani o bug dell’applicazione. Usando i giusti criteri di ricerca e producendo i risultati in modo chiaro e conciso, puoi identificare rapidamente righe o valori duplicati e prendere provvedimenti per correggerli.
Utilizzo della Funzione COUNT
Un modo per trovare i duplicati in SQL è utilizzare la funzione COUNT. La funzione COUNT è una funzione aggregata che conta il numero di righe in una tabella che soddisfano una determinata condizione. Usando la funzione COUNT, puoi contare il numero di occorrenze di un particolare valore in una colonna e identificare i duplicati.
Per usare la funzione COUNT per trovare i duplicati, dovrai raggruppare le righe per la colonna che vuoi controllare per i duplicati. La clausola GROUP BY viene utilizzata per raggruppare le righe in base ai valori in una colonna specifica. Per esempio, se vuoi trovare i duplicati nella colonna “email” di una tabella “users”, raggrupperesti le righe per la colonna “email”.
Ecco un esempio di query che usa la funzione COUNT per trovare i duplicati nella colonna “email” di una tabella “users”:
SELECT email, COUNT(email) as count
FROM users
GROUP BY email
HAVING COUNT(email) > 1;
In questa query, la clausola GROUP BY raggruppa le righe per la colonna “email” e la funzione COUNT conta il numero di occorrenze di ogni indirizzo email. La clausola HAVING filtra i risultati per mostrare solo gli indirizzi email che hanno più di una occorrenza.
Il risultato di questa query sarà una tabella che mostra gli indirizzi email che hanno duplicati e il numero di occorrenze di ogni indirizzo email. Puoi usare queste informazioni per identificare e rimuovere le righe duplicate dalla tabella.
Usare la funzione COUNT è un modo semplice ed efficace per trovare i duplicati in SQL. Ti permette di identificare rapidamente i valori duplicati in una colonna e prendere provvedimenti per rimuoverli dalla tabella.
Utilizzo della Clausola INNER JOIN
Uno dei modi più comuni per trovare i duplicati in SQL è utilizzare la clausola INNER JOIN. Questa clausola permette di combinare due o più tabelle in base a una colonna comune e restituire solo le righe che hanno valori corrispondenti in entrambe le tabelle.
Per usare la clausola INNER JOIN per trovare i duplicati, dovrai identificare le colonne che contengono i dati duplicati. Una volta identificate queste colonne, puoi usare la clausola INNER JOIN per unire la tabella su queste colonne.
Ecco un esempio di come usare la clausola INNER JOIN per trovare i duplicati in una tabella chiamata “orders”:
SELECT o1.order_id, o2.order_id
FROM orders o1
INNER JOIN orders o2
ON o1.customer_id = o2.customer_id
AND o1.order_date = o2.order_date
AND o1.order_id <> o2.order_id;
In questo esempio, la clausola INNER JOIN viene utilizzata per unire la tabella “orders” con se stessa, usando le colonne “customer_id” e “order_date” come criteri di join. L’operatore “AND” viene utilizzato per specificare che tutte e tre le colonne devono corrispondere affinché una riga venga restituita. L’ultima riga della query, “AND o1.order_id <> o2.order_id”, assicura che la query non restituisca righe dove entrambi i valori “order_id” sono uguali.
Il risultato di questa query sarà un elenco di tutti gli ordini che hanno lo stesso ID cliente e data ordine, ma ID ordine diversi. Questi sono gli ordini duplicati che necessitano di ulteriore indagine.
Pratica con i self-join:
[[ testData.title ]]
Interroga la tabella products per trovare tutti i record di prodotti duplicati (stesso product_name e category). Restituisci product_id, product_name, category e price solo per i record duplicati (non la prima occorrenza).
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Tabelle Disponibili
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Usare la clausola INNER JOIN in questo modo può essere uno strumento potente per trovare i duplicati in SQL. Tuttavia, è importante essere cauti quando si usa questo metodo, poiché può essere facile restituire accidentalmente falsi positivi o perdere duplicati che sono distribuiti su più tabelle. È sempre una buona idea ricontrollare i risultati e usare altri metodi, come le clausole GROUP BY e HAVING, per confermare le proprie scoperte.
Prova tu stesso:
[[ testData.title ]]
Interroga la tabella customers per restituire i record completi dei clienti (name e email) il cui email compare più di una volta. Usa una sottoquery per identificare le email duplicate.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Tabelle Disponibili
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Trovare Coppie Duplicate Usando i Self-Join
Un’altra tecnica potente per trovare i duplicati è usare i self-join per identificare coppie di record che condividono caratteristiche comuni. Questo approccio è particolarmente utile quando vuoi trovare coppie duplicate esatte piuttosto che semplicemente identificare che esistono duplicati.
Un self-join comporta l’unione di una tabella con se stessa usando alias diversi. Unendo sulle colonne che definiscono i duplicati e assicurandosi di non abbinare un record con se stesso, è possibile identificare efficacemente le coppie duplicate.
Per esempio, se hai una tabella di transazioni e vuoi trovare coppie di transazioni con lo stesso ID cliente e importo ma ID transazione diversi, puoi usare un self-join come questo:
SELECT t1.transaction_id as transaction_id1,
t2.transaction_id as transaction_id2,
t1.customer_id,
t1.amount
FROM transactions t1
INNER JOIN transactions t2
ON t1.customer_id = t2.customer_id
AND t1.amount = t2.amount
AND t1.transaction_id < t2.transaction_id;
I punti chiave in questa query sono:
-
t1et2sono alias per la stessa tabella - Le condizioni di join specificano cosa rende i record “duplicati” (
customer_ideamount) -
t1.transaction_id < t2.transaction_idassicura che otteniamo ogni coppia solo una volta e non abbiniamo un record con se stesso
Prova tu stesso:
[[ testData.title ]]
Interroga la tabella transactions per trovare coppie di transazioni che hanno lo stesso customer_id e amount ma diverso transaction_id. Restituisci transaction_id1, transaction_id2, customer_id e amount per ogni coppia duplicata. Mostra ogni coppia solo una volta (evita di mostrare sia A-B che B-A).
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Tabelle Disponibili
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Trovare i Duplicati Usando le Common Table Expression (CTE)
Uno dei modi per trovare i duplicati in SQL è utilizzare le Common Table Expression (CTE). Una CTE è un set di risultati temporaneo che viene definito nell’ambito dell’esecuzione di una singola istruzione SELECT, INSERT, UPDATE, DELETE o CREATE VIEW.
Per trovare i duplicati usando CTE, si può usare la funzione ROW_NUMBER(), che assegna un numero sequenziale univoco a ogni riga all’interno di una partizione di un set di risultati. La clausola PARTITION BY specifica le colonne usate per definire la partizione, e la clausola ORDER BY specifica l’ordine delle righe all’interno di ogni partizione.
Ecco un esempio di utilizzo di CTE per trovare i duplicati:
WITH CTE AS (
SELECT column1, column2, column3, ROW_NUMBER() OVER(PARTITION BY column1, column2, column3 ORDER BY column1, column2, column3) AS RowNumber
FROM table_name
)
SELECT *
FROM CTE
WHERE RowNumber > 1
In questo esempio, la CTE viene definita con le colonne da controllare per i duplicati. La funzione ROW_NUMBER() viene utilizzata per generare un numero di sequenza per ogni riga all’interno di una partizione del set di risultati, dove la partizione è definita dalle colonne specificate nella clausola PARTITION BY. Il set di risultati viene poi filtrato per mostrare solo le righe dove il RowNumber è maggiore di 1, indicando che ci sono duplicati.
È importante notare che la clausola ORDER BY all’interno della funzione ROW_NUMBER() deve corrispondere alla clausola ORDER BY nell’istruzione SELECT principale, altrimenti i risultati potrebbero non essere accurati.
Usare CTE per trovare i duplicati può essere particolarmente utile in SQL Server 2017, che ha introdotto il supporto per l’elaborazione di grafi usando le Common Table Expression. Questo permette query più complesse che coinvolgono relazioni tra i dati.
Nel complesso, usare CTE per trovare i duplicati in SQL può essere uno strumento potente per l’analisi e la gestione dei dati.
Prova tu stesso:
[[ testData.title ]]
Interroga la tabella products usando una Common Table Expression (CTE) per trovare nomi di prodotti duplicati. La CTE deve raggruppare per nome prodotto e contare le occorrenze, poi selezionare i prodotti con conteggio > 1.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Tabelle Disponibili
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Trovare i Duplicati Usando le Funzioni Finestra
Quando si tratta di trovare i duplicati in SQL, uno dei modi più efficienti è usare le funzioni finestra. Le funzioni finestra sono uno strumento potente che può essere usato per eseguire calcoli su un insieme di righe che sono correlate alla riga corrente.
Per trovare i duplicati usando le funzioni finestra, puoi usare la funzione ROW_NUMBER() in combinazione con una clausola PARTITION BY. La funzione ROW_NUMBER() assegna un numero univoco a ogni riga all’interno di una partizione, e la clausola PARTITION BY raggruppa le righe in partizioni basate su una colonna specifica o un insieme di colonne.
Per esempio, supponiamo di avere una tabella di utenti che include colonne per user_id, username e email. Per trovare tutti gli utenti che hanno email duplicate, puoi usare la seguente istruzione select:
SELECT user_id, username, email
FROM (
SELECT user_id, username, email,
ROW_NUMBER() OVER (PARTITION BY email ORDER BY user_id) AS row_num
FROM users
) AS subquery
WHERE row_num > 1;
In questo esempio, la clausola PARTITION BY partiziona le righe per la colonna email, e la funzione ROW_NUMBER() assegna un numero univoco a ogni riga all’interno della partizione basato sulla colonna user_id. La clausola WHERE filtra tutte le righe tranne quelle con un row_num maggiore di 1, che sono le righe con email duplicate.
Pratica con ROW_NUMBER():
[[ testData.title ]]
Interroga la tabella customers per restituire i record completi dei clienti (name e email) il cui email compare più di una volta. Usa una sottoquery per identificare le email duplicate.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Tabelle Disponibili
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
È importante notare che le funzioni finestra possono essere usate in combinazione con altre funzioni SQL, come le istruzioni CASE e le funzioni aggregate, per creare query più complesse. Per esempio, potresti usare un’istruzione CASE per raggruppare le righe in una categoria specifica, e poi usare una funzione finestra per trovare i duplicati all’interno di quella categoria.
In conclusione, usare le funzioni finestra per trovare i duplicati in SQL può essere un metodo potente ed efficiente. Usando la funzione ROW_NUMBER() in combinazione con una clausola PARTITION BY, puoi facilmente raggruppare le righe in partizioni e assegnare numeri univoci a ogni riga all’interno della partizione. Questo ti permette di identificare e rimuovere rapidamente le righe duplicate dai tuoi risultati.
Prova tu stesso:
[[ testData.title ]]
Interroga la tabella products per trovare tutti i record di prodotti duplicati (stesso product_name e category). Restituisci product_id, product_name, category e price solo per i record duplicati (non la prima occorrenza).
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Tabelle Disponibili
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Utilizzo della Funzione ROW_NUMBER() con la Clausola PARTITION BY
Quando si cercano duplicati in un database SQL, uno strumento utile è la funzione ROW_NUMBER() con la clausola PARTITION BY. Questa funzione assegna un numero univoco a ogni riga in un set di risultati, basato sui criteri di partizionamento specificati.
La clausola PARTITION BY permette all’utente di raggruppare le righe in partizioni basate su una o più colonne. Questo significa che la funzione ROW_NUMBER() assegnerà un numero univoco a ogni riga all’interno di ogni partizione, piuttosto che attraverso l’intero set di risultati.
Per esempio, considera una tabella di ordini clienti con colonne per ID ordine, ID cliente e data ordine. Per trovare ordini duplicati per ogni cliente, si potrebbe usare la seguente query:
SELECT order_id, customer_id, order_date,
ROW_NUMBER() OVER (PARTITION BY customer_id, order_date
ORDER BY order_id) AS row_num
FROM orders
In questa query, la funzione ROW_NUMBER() viene usata con la clausola PARTITION BY per raggruppare gli ordini per cliente e data ordine. La funzione poi assegna un numero univoco a ogni riga all’interno di ogni partizione, basato sull’ID ordine.
La tabella risultante avrà una colonna aggiuntiva chiamata “row_num” che contiene i numeri di riga assegnati. I duplicati possono poi essere identificati selezionando le righe con row_num maggiore di 1.
Usare la funzione ROW_NUMBER() con la clausola PARTITION BY può essere uno strumento potente per trovare i duplicati nei database SQL. Raggruppando le righe in partizioni basate su criteri specifici, la funzione può assegnare numeri univoci a ogni riga all’interno di ogni partizione, rendendo più facile identificare i duplicati.
Utilizzo dell’Istruzione CASE con la Funzione ROW_NUMBER()
In SQL, la funzione ROW_NUMBER() viene usata per assegnare un numero sequenziale univoco a ogni riga in un set di risultati. Questa funzione può essere usata in congiunzione con l’istruzione CASE per identificare record duplicati in una tabella.
L’istruzione CASE permette di applicare logica condizionale a ogni riga in un set di risultati. Utilizzando la funzione ROW_NUMBER() all’interno dell’istruzione CASE, il numero di occorrenze di ogni record può essere determinato.
Per esempio, la seguente query SQL può essere usata per trovare record duplicati in una tabella “users” basandosi sulle colonne “first_name” e “last_name”:
SELECT *,
CASE
WHEN ROW_NUMBER() OVER (PARTITION BY first_name, last_name ORDER BY id) > 1
THEN 'Duplicato'
ELSE 'Unico'
END AS duplicate_status
FROM users;
La query sopra partiziona il set di risultati per le colonne “first_name” e “last_name” e ordina le righe per la colonna “id”. La funzione ROW_NUMBER() assegna un numero sequenziale univoco a ogni riga all’interno di ogni partizione.
L’istruzione CASE poi controlla se il valore ROW_NUMBER() è maggiore di 1. Se lo è, allora la riga viene identificata come duplicato. Se non lo è, la riga viene identificata come unica.
Il set di risultati includerà una colonna aggiuntiva chiamata “duplicate_status” che mostra “Duplicato” o “Unico” per ogni riga.
| id | first_name | last_name | duplicate_status | |
|---|---|---|---|---|
| 1 | John | Smith | john@example.com | Unico |
| 2 | Jane | Doe | jane@example.com | Unico |
| 3 | John | Smith | john.smith@example.com | Duplicato |
| 4 | Bob | Johnson | bob@example.com | Unico |
| 5 | Jane | Doe | jane.doe@example.com | Duplicato |
Nell’esempio sopra, le righe 1, 2 e 4 sono identificate come uniche, mentre le righe 3 e 5 sono identificate come duplicati basandosi sulle colonne “first_name” e “last_name”.
Utilizzando la funzione ROW_NUMBER() all’interno dell’istruzione CASE, i record duplicati possono essere facilmente identificati e gestiti in una tabella SQL.
Beekeeper Studio È Una GUI per Database Gratuita e Open Source
Il miglior strumento per query SQL ed editor che abbia mai usato. Fornisce tutto ciò di cui ho bisogno per gestire il mio database. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio è veloce, intuitivo e facile da usare. Beekeeper supporta molti database e funziona benissimo su Windows, Mac e Linux.
Cosa Dicono Gli Utenti Di Beekeeper Studio
"Beekeeper Studio ha completamente sostituito il mio vecchio workflow con SQL. È veloce, intuitivo e rende di nuovo piacevole lavorare con i database."
"Ho provato molte GUI per database, ma Beekeeper trova il perfetto equilibrio tra funzionalità e semplicità. Funziona e basta."