Vai al contenuto principale

Pulizia dei dati in SQL

In questo tutorial imparerai tecniche per ripulire dati disordinati in SQL, una competenza imprescindibile per ogni data scientist.
Aggiornato 29 set 2026  · 10 min leggi

Scopri con l'IA

ChatGPTClaudePerplexity

I dati del mondo reale sono quasi sempre disordinati. Che tu sia data scientist, data analyst o anche sviluppatore, se devi scoprire informazioni sui dati è fondamentale assicurarti che siano abbastanza puliti per farlo. Esiste una definizione ben strutturata di tidy data; puoi consultare questa pagina wiki per approfondire.

In questo tutorial metterai in pratica alcune delle tecniche di pulizia dei dati più comuni in SQL. Creerai un tuo dataset fittizio, ma le tecniche possono essere applicate anche a dati reali (in formato tabellare). C'è molto da coprire. Cominciamo!

Nota: dovresti già sapere come scrivere query SQL di base in PostgreSQL (l'RDBMS che userai in questo tutorial). Se hai bisogno di ripassare i concetti, di seguito trovi alcune risorse utili:

Diversi tipi di dati, i loro valori disordinati e i rimedi

Nel formato tabellare, i tipi di dato più comuni sono string, numeric o date-time. Puoi imbatterti in valori disordinati in ciascuno di questi tipi. Vediamo ora ognuno di questi tipi con esempi dei rispettivi valori disordinati. Iniziamo con il tipo numeric.

Numeri disordinati

I numeri possono presentarsi in forme disordinate in vari modi. Qui vedrai i casi più comuni:

  • Tipo indesiderato/Incongruenza di tipo: Supponi che ci sia una colonna chiamata age in un dataset su cui stai lavorando. Vedi che i valori presenti in quella colonna sono di tipo float — valori come 23.0, 45.0, 34.0 e così via. In questo caso, non hai bisogno che la colonna age sia di tipo float. Non è così?

  • Valori null: Anche se è particolarmente comune con tutti i tipi di dato menzionati sopra, qui i valori null significano semplicemente che i valori non sono disponibili/vuoti. Tuttavia, i valori null possono essere presenti anche in altre forme. Prendi ad esempio il dataset Pima Indian Diabetes. Il dataset contiene valori zero per colonne come Plasma glucose concentration, Diastolic blood pressure, il che è praticamente non valido. Se esegui un'analisi statistica sul dataset senza occuparti di queste voci non valide, la tua analisi non sarà accurata.

Studiamo ora i problemi che possono sorgere da queste questioni e come affrontarli.

Problemi con i numeri disordinati e come gestirli

Vediamo ora i problemi più comuni che potresti incontrare se non pulisci i dati disordinati (rispetto ai tipi menzionati sopra).

1. Aggregazione dei dati

Supponi di avere voci null per una colonna numerica e di calcolare statistiche descrittive (come media, massimo, minimo) su quella colonna. In questo caso i risultati non verranno rappresentati accuratamente. Considera di nuovo il dataset Pima Indian Diabetes con le voci zero non valide. Se calcolassi le statistiche sulle colonne come detto prima, otterresti i risultati giusti? I risultati non sarebbero errati? Come affrontare questo problema? Ci sono vari modi:

- Removing the entries containing missing/null values (not recommended)
- Imputing the null entries with a numeric value (typically with mean or median of the respective column)

Passiamo ora alla pratica con questi problemi e con la seconda opzione per combattere i valori null.

Considera la seguente tabella PostgreSQL chiamata entries:

tabella PostgreSQL

Nel prospetto sopra vedi due voci null. Supponi di voler ottenere il valore medio del peso da questa tabella ed esegui la seguente query:

select avg(weight_in_lbs) as average_weight_in_lbs from entries;

Ottieni 90.45 come output. È corretto? Cosa si può fare? Riempiamo la voce null con questo valore medio usando la funzione COALESCE().

Riempiamo prima i valori mancanti con COALESCE() (ricorda che COALESCE() non modifica i valori nella tabella originale, restituisce solo una vista temporanea della tabella con i valori cambiati):

select *, COALESCE(weight_in_lbs, 90.45) as corrected_weights from entries;

Dovresti ottenere un output come:

output

Ora puoi applicare di nuovo AVG():

select avg(corrected_weights) from
(select *, COALESCE(weight_in_lbs, 90.45) as corrected_weights from entries) as subquery;

Questo è un risultato molto più accurato rispetto al precedente. Vediamo ora un altro problema che può verificarsi se ci sono incongruenze nei tipi di dato delle colonne.

2. Join tra tabelle

Immagina di lavorare con le seguenti tabelle student_metadata e department_details:

tabelle

Nella tabella student_mtadata, dept_id è di tipo intero, mentre nella tabella department_details è di tipo testo. Ora, supponi di voler unire queste due tabelle e produrre un report che contenga le seguenti colonne:

  • id
  • name
  • dept_name

Per farlo, esegui questa query:

select id, name, dept_name from
student_metadata s join department_details d
on s.dept_id = d.dept_id;

Incontri quindi questo errore:

ERROR: operator does not exist: smallint = text

Ecco un'infografica molto chiara che illustra il problema (dal corso di DataCamp Reporting in SQL):

infografica

Questo accade perché i tipi di dato non corrispondono durante il join delle due tabelle. Qui puoi fare il CAST della colonna dept_id nella tabella department_details a intero mentre unisci le tabelle. Ecco come farlo:

select id, name, dept_name from
student_metadata s join department_details d
on s.dept_id = cast(d.dept_id as smallint);

E ottieni il report desiderato:

report

Passiamo ora a come le stringhe possano presentarsi in forme disordinate, ai relativi problemi e a come affrontarli.

Stringhe disordinate e come pulirle

I valori di tipo stringa sono anch'essi molto comuni. Iniziamo questa sezione osservando i valori di una colonna dept_name (che indica i nomi dei reparti) tratta da una tabella chiamata student_details:

tabella

Valori stringa come quelli sopra possono causare molti problemi imprevisti. I.T, Information Technology e i.t indicano tutti lo stesso reparto, cioè Information Technology, e supponi che il documento di specifica richieda che i valori siano presenti solo come I.T. Ora, diciamo che vuoi contare il numero di studenti appartenenti al reparto I.T. ed esegui questa query:

select dept_name, count(dept_name) as student_count
from student_details
group by dept_name;

E ottieni:

output

È un report accurato? No! Come puoi risolvere questo problema?

Identifichiamo prima il problema in modo più dettagliato:

  • Hai Information Technology come valore che dovrebbe essere convertito in I.T e
  • hai i.t come altro valore che dovrebbe essere convertito in I.T.

Nel primo caso puoi REPLACE il valore Information Technology con I.T, e nel secondo caso converti i caratteri in maiuscolo con UPPER. Puoi ottenere tutto in un'unica query, anche se è consigliabile affrontare questo tipo di problemi passo dopo passo. Ecco la query per risolvere il problema:

select upper(replace(dept_name, 'Information Technology', 'I.T')) as dept_cleaned,
count(dept_name) as student_count
from student_details
group by dept_cleaned;

E il report:

report

Puoi leggere di più sulle funzioni per le stringhe in PostgreSQL qui.

Passiamo ora a qualche esempio di come i valori date possano essere disordinati e cosa puoi fare per ripulirli.

Date disordinate e come pulirle

Immagina di lavorare con una tabella chiamata employees che contiene una colonna birthdate ma non con un tipo date appropriato. Ora vuoi eseguire query con funzioni dedicate alle date come DATE_PART(). Non potrai farlo finché non esegui il CAST della colonna birthdate al tipo date. Vediamolo in azione.

Considera che le birthdate siano nel formato YYYY-MM-DD.

Ecco com'è la tabella employees:

tabella employees

Ora esegui la seguente query per estrarre i mesi dalle date di nascita:

select date_part('month', birthdate) from employees;

E ottieni subito questo errore:

ERROR: function date_part(unknown, text) does not exist

Insieme all'errore, ricevi anche un ottimo suggerimento:

HINT: No function matches the given name and argument types. You might need to add explicit type casts.

Seguiamo il suggerimento ed eseguiamo il CAST di birthdate al tipo date appropriato, quindi applichiamo DATE_PART():

select date_part('month', CAST(birthdate AS date)) as birthday_months from employees;

Dovresti ottenere il risultato:

risultato

Procediamo ora alla sezione pre-conclusiva di questo tutorial, in cui studierai gli effetti delle duplicazioni di dati e come gestirle.

Duplicazioni di dati: cause, effetti e soluzioni

In questa sezione studierai alcune delle cause più comuni che portano a duplicazioni di dati. Vedrai anche i loro effetti e alcuni modi per prevenirle. Considera le seguenti due tabelle band_details e some_festival_record:

tabelle

La tabella band_details riporta informazioni sulle band musicali: contiene i loro identificativi, i nomi e il numero totale di spettacoli effettuati. La tabella some_festival_record, invece, rappresenta un ipotetico festival musicale e contiene i record delle band che vi hanno suonato.

Ora, supponi di voler produrre un report che contenga i nomi delle band, il conteggio dei loro spettacoli e il numero totale di volte in cui hanno suonato al festival. Qui serve un INNER join. Esegui la seguente query:

select band_name, sum(total_show_count) as total_shows, sum(performed) as total_times_performed
from band_details b join some_festival_record s
on b.id = s.band_id
group by band_name;

E la query produce:

risultato della query

Non pensi che i valori di total_shows siano errati qui? Perché dalla tabella band_details sai che Band_1 ha effettuato in totale 36 spettacoli. Allora cos'è andato storto? Duplicati!

Unendo le due tabelle, hai aggregato per errore la colonna total_show_count, causando una duplicazione dei dati nei risultati intermedi del join. Se rimuovi l'aggregazione e modifichi la query di conseguenza, dovresti ottenere i risultati desiderati:

select band_name, total_show_count, sum(performed) as total_times_performed
from band_details b join some_festival_record s
on b.id = s.band_id
group by band_name, total_show_count;

Ora ottieni i risultati attesi:

risultati attesi

C'è un altro modo per prevenire la duplicazione dei dati, cioè aggiungere un altro campo nella clausola JOIN in modo che le tabelle vengano unite con condizioni più restrittive.

Puoi usare questo file .SQL per generare le tabelle usate qui e anche i valori mostrati.

Per approfondire

Grazie per aver letto questo tutorial. Ti ha introdotto a uno dei passaggi più importanti nella pipeline di analisi dei dati: la pulizia dei dati. Hai visto diverse forme di dati disordinati e come affrontarle. Esistono però tecniche più avanzate per gestire problemi di pulizia più complessi e, se vuoi approfondire, di seguito trovi alcuni eccellenti corsi DataCamp che puoi seguire:

Sentiti libero di condividere le tue opinioni nella sezione Comments.

Argomenti
SQL

Corsi SQL

Corso

Manipolazione dei dati in SQL

4 ore
338.8K
Padroneggia query SQL complesse per rispondere a varie domande di Data Science e preparare dataset solidi da analizzare in PostgreSQL.
Vedi i dettagliRight Arrow
Inizia Il Corso
Mostra altroRight Arrow
Correlato

blog

Che cos'è Snowflake? Guida per principianti alla piattaforma dati cloud

Esplora le basi di Snowflake, la piattaforma dati cloud. Scopri la sua architettura, le sue funzionalità e come integrarla nelle tue pipeline di dati.
Tim Lu's photo

Tim Lu

12 min

blog

Tokenizzazione nel NLP: come funziona, sfide e casi d'uso

Guida al preprocessing NLP nel machine learning. Copriamo spaCy, i transformer di Hugging Face e come funziona la tokenizzazione in casi d'uso reali.
Abid Ali Awan's photo

Abid Ali Awan

10 min

blog

I 15 migliori server MCP remoti che ogni AI builder dovrebbe conoscere nel 2026

Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Abid Ali Awan's photo

Abid Ali Awan

15 min

Mostra AltroMostra Altro