1. Introduction
Les données brutes sont rarement exploitables directement. Avant toute analyse ou modélisation, une étape de nettoyage est indispensable : suppression des doublons, traitement des valeurs manquantes, standardisation des formats, correction des incohérences.
Dans ce cas pratique, nous allons nettoyer un dataset de ventes de 63 000 lignes généré aléatoirement avec Faker. Les problèmes sont variés et réalistes : doublons, valeurs manquantes, dates mal formatées, paiements non standardisés, quantités aberrantes, prix à zéro, et incohérences de calcul.
Objectif pédagogique
À l’issue de ce cas pratique, vous saurez :
- Importer un CSV dans SQLite
- Inspecter la qualité des données avec SQL
- Nettoyer les problèmes courants (doublons, NULL, formats)
- Exporter un dataset propre

Figure 1 : Le dataset brut contient 63 000 lignes.
2. Présentation du dataset
Le dataset raw_sales_data_56k.csv contient des ventes simulées avec des erreurs volontaires pour illustrer les problèmes récurrents de qualité des données.
Téléchargement raw_sales_data_56k.csv (6.95 Mo)
Métadonnées description.txt
Licence CC BY-NC 4.0
Structure 63 000 lignes × 11 colonnes
Colonnes du dataset :
Transaction_ID: identifiant unique de la transactionSale_Date: date de la vente (formats variés)Customer_ID: identifiant clientCustomer_Email: email client (avec valeurs manquantes)Product_Category: catégorie produit (casse variable, espaces)Product_Name: nom du produitQuantity: quantité achetée (TEXT, valeurs aberrantes)Unit_Price: prix unitaire (NULL, zéro)Total_Amount: montant total (incohérent avec Quantity × Unit_Price)Store_Location: localisation du magasin (casse variable)Payment_Method: moyen de paiement (non standardisé)

Figure 2 : Aperçu du dataset brut – on observe déjà des NULL et des formats incohérents.

Figure 3 : Structure des colonnes – on note que Quantity est en TEXT au lieu de INTEGER.
3. Environnement technique
Pour ce cas pratique, nous utilisons :
- SQLite : base de données légère, sans installation serveur
- DB Browser for SQLite : interface graphique pour exécuter les requêtes
- Fichier unique : `sales_cleaning.db` – portable et reproductible
Pourquoi SQLite ?
SQLite est parfait pour ce type d’exercice : zéro configuration, un seul fichier, et le langage SQL standard (sauf quelques fonctions spécifiques). Les requêtes présentées sont adaptables à PostgreSQL, MySQL ou SQL Server.

Figure 4 : Import du fichier CSV dans DB Browser.
Erreur fréquente à l’import
Lors de l’import, la ligne d’en-tête a été importée comme une ligne de données. Nous avons dû la supprimer manuellement. Voici la requête utilisée :
DELETE FROM raw_sales WHERE Transaction_ID = 'Transaction_ID';
4. Inspection initiale des données
4.1 Comptage des lignes
Nombre total de transactions
SELECT COUNT(*) FROM raw_sales;Résultat : 63 000 lignes
4.2 Structure des colonnes
Types de données
PRAGMA table_info(raw_sales);Observation : La colonne `Quantity` est au format TEXT au lieu de INTEGER – à corriger.
4.3 Identification des problèmes

Valeurs manquantes :
- Customer_Email : 2 845 NULL (~4,5%)
- Product_Category : 908 NULL (~1,4%)
- Quantity : 1 711 NULL (~2,7%)
- Unit_Price : 2 915 NULL (~4,6%)

Dates incohérentes : mélange de YYYY-MM-DD, YYYY/MM/DD, MM-DD-YYYY, et même du texte (“Jan 2024 (approx)”).

Payment_Method : 9 valeurs distinctes (“Credit Card”, “cc”, “PayPal”, “ppal”, etc.) – à standardiser.

Casse et espaces : “HOME GOODS”, “Home Goods”, “home goods” – à uniformiser.

Quantités aberrantes : valeurs négatives (-1) et absurdes (9999).

Prix à zéro : 20 lignes avec Unit_Price = 0 (à corriger).

Incohérence Total_Amount : 11 059 lignes où Total_Amount ≠ Quantity × Unit_Price.
5. Nettoyage des données
5.1 Création d’une table de travail
Table de travail
CREATE TABLE clean_sales AS SELECT * FROM raw_sales;5.2 Correction des types de données
Quantity en INTEGER
CREATE TABLE clean_sales_fixed AS
SELECT
Transaction_ID,
Sale_Date,
Customer_ID,
Customer_Email,
Product_Category,
Product_Name,
CAST(Quantity AS INTEGER) AS Quantity,
Unit_Price,
Total_Amount,
Store_Location,
Payment_Method
FROM clean_sales;
DROP TABLE clean_sales;
ALTER TABLE clean_sales_fixed RENAME TO clean_sales;5.3 Suppression des doublons
Suppression des doublons exacts
DELETE FROM clean_sales
WHERE rowid NOT IN (
SELECT MIN(rowid)
FROM clean_sales
GROUP BY Transaction_ID, Sale_Date, Customer_ID, Customer_Email,
Product_Category, Product_Name, Quantity, Unit_Price,
Total_Amount, Store_Location, Payment_Method
);Résultat : 167 doublons supprimés.

5.4 Standardisation des dates
Création d’une colonne date propre
ALTER TABLE clean_sales ADD COLUMN Sale_Date_Clean TEXT;
UPDATE clean_sales
SET Sale_Date_Clean = SUBSTR(Sale_Date, 1, 10)
WHERE Sale_Date GLOB '*-*-*' AND LENGTH(Sale_Date) = 10;
UPDATE clean_sales
SET Sale_Date_Clean = Sale_Date
WHERE Sale_Date_Clean IS NULL;
5.5 Nettoyage du texte (UPPER + TRIM)
Product_Category et Store_Location
UPDATE clean_sales SET Product_Category = UPPER(TRIM(Product_Category));
UPDATE clean_sales SET Store_Location = UPPER(TRIM(Store_Location));

5.6 Standardisation des méthodes de paiement
Payment_Method uniformisée
UPDATE clean_sales
SET Payment_Method = CASE
WHEN Payment_Method IN ('Credit Card', 'cc') THEN 'Credit Card'
WHEN Payment_Method IN ('PayPal', 'ppal') THEN 'PayPal'
WHEN Payment_Method IN ('Debit Card', 'debit') THEN 'Debit Card'
WHEN Payment_Method IS NULL THEN 'Unknown'
ELSE Payment_Method
END;
5.7 Correction des quantités aberrantes
Mise à NULL des valeurs aberrantes
UPDATE clean_sales SET Quantity = NULL WHERE Quantity < 0 OR Quantity > 1000;
5.8 Correction des prix à zéro
Mise à NULL des Unit_Price = 0
UPDATE clean_sales SET Unit_Price = NULL WHERE Unit_Price = 0;Résultat : 20 lignes corrigées.

5.9 Imputation des valeurs manquantes
Imputation de Quantity (médiane)
Imputation par la médiane
UPDATE clean_sales
SET Quantity = (
SELECT AVG(Quantity)
FROM (
SELECT Quantity
FROM clean_sales
WHERE Quantity IS NOT NULL
ORDER BY Quantity
LIMIT 2 - (SELECT COUNT(*) FROM clean_sales WHERE Quantity IS NOT NULL) % 2
OFFSET (SELECT (COUNT(*) - 1) / 2 FROM clean_sales WHERE Quantity IS NOT NULL)
)
)
WHERE Quantity IS NULL;
Imputation de Unit_Price (moyenne)
Imputation par la moyenne
UPDATE clean_sales
SET Unit_Price = (SELECT AVG(Unit_Price) FROM clean_sales WHERE Unit_Price IS NOT NULL)
WHERE Unit_Price IS NULL;Résultat : 2 935 lignes imputées.

5.10 Recalcul de Total_Amount
Recalculer là où c’est incohérent
UPDATE clean_sales
SET Total_Amount = Quantity * Unit_Price
WHERE Total_Amount != Quantity * Unit_Price;Résultat : 15 445 lignes recalculées.

6. Vérification finale
62 833
lignes après nettoyage
-167 doublons
0
valeurs manquantes sur colonnes clés
0
incohérences Total_Amount
Vérification des NULL
SELECT
COUNT(CASE WHEN Customer_Email IS NULL THEN 1 END) AS missing_email,
COUNT(CASE WHEN Quantity IS NULL THEN 1 END) AS missing_quantity,
COUNT(CASE WHEN Unit_Price IS NULL THEN 1 END) AS missing_price
FROM clean_sales;Résultat de la vérification :
- ✅ Plus aucun doublon
- ✅ Plus de valeurs manquantes sur les colonnes critiques
- ✅ Tous les Total_Amount sont cohérents
- ✅ Les catégories et localisations sont uniformisées (UPPER CASE)
- ✅ Les méthodes de paiement sont standardisées
7. Export du dataset propre
Export en CSV
-- Dans DB Browser : Fichier → Exporter → Table(s) CSV
-- Ou via SQLite CLI :
.headers on
.mode csv
.output clean_sales_data.csv
SELECT * FROM clean_sales;Télécharger le dataset nettoyé clean_sales_data.csv (7.64 Mo)
Fichier SQLite sales_cleaning.db (22.81 Mo)
8. Bonnes pratiques à retenir
1. Toujours travailler sur une copie
Créez une table de travail avant toute modification destructive.
2. Vérifier les types de données à l’import
Assurez-vous que les colonnes numériques sont bien importées en INTEGER/REAL.
3. Documenter les transformations
Gardez une trace des requêtes exécutées pour reproduire le nettoyage.
4. Utiliser des transactions pour les opérations critiques
BEGIN; ... COMMIT; permet d’annuler en cas d’erreur.
FAQ
Pourquoi utiliser SQL plutôt qu'Excel pour nettoyer des données ?
SQL est plus rapide sur les gros volumes (63 000 lignes, Excel commence à ramer), plus reproductible (les requêtes peuvent être réexécutées), et plus puissant pour les transformations complexes (jointures, sous-requêtes, window functions).
Les mêmes requêtes fonctionnent-elles sur PostgreSQL/MySQL ?
Globalement oui, avec quelques adaptations : la fonction GLOB est spécifique à SQLite (remplacer par LIKE ou REGEXP). L'imputation par médiane sera plus simple avec PERCENTILE_CONT (PostgreSQL) ou NTILE.
Comment gérer les dates plus proprement ?
SQLite n'a pas de type DATE natif. Pour un usage professionnel, préférez PostgreSQL ou MySQL, et utilisez DATE() pour normaliser. Dans notre cas, nous avons simplifié en extrayant les 10 premiers caractères des formats standard.
Que faire si mon dataset contient des millions de lignes ?
SQLite peut gérer des millions de lignes, mais les performances peuvent diminuer. Passez alors à PostgreSQL ou utilisez des index sur les colonnes de filtrage. Évitez les SELECT DISTINCT * et préférez les GROUP BY ciblés.
Pourquoi utiliser la médiane pour Quantity et la moyenne pour Unit_Price ?
La quantité a une distribution asymétrique (petites valeurs fréquentes, quelques outliers). La médiane est plus robuste. Le prix unitaire a une distribution plus symétrique, la moyenne est acceptable.
Faites parler vos données
Apprenez les méthodes et les outils pour extraire de la valeur stratégique : Data Science : Le guide complet des méthodes et outils.
10. Conclusion
Ce cas pratique montre comment SQL permet de nettoyer efficacement un dataset de taille réelle (63 000 lignes) avec des problèmes variés. En une vingtaine de requêtes, nous avons :
- Supprimé 167 doublons
- Corrigé les types de données
- Traité 2 845 emails manquants
- Imputé 1 711 quantités et 2 915 prix unitaires
- Standardisé 62 833 catégories et localisations
- Unifié 9 méthodes de paiement en 4 catégories
- Recalculé 15 445 montants totaux incohérents
À retenir
- Le nettoyage de données représente 60 à 80% du temps d’un projet data
- SQL est un outil puissant pour le nettoyage à grande échelle
- Les étapes clés : inspection, correction des types, doublons, NULL, standardisation, vérification
- Toujours travailler sur une copie et documenter les transformations
Pour aller plus loin : Découvrez notre guide complet sur le nettoyage de données avec SQL pour des techniques avancées.