Aller au contenu

Module 6 : Pivot et Unpivot

·3 mins·
SQL Formation
SQL - Cet article fait partie d'une série.
Partie 6: Cet article

Le PIVOT / UNPIVOT est indispensable dès qu’on veut restructurer ses données, par exemple passer de lignes → colonnes (ou l’inverse). C’est l’équivalent SQL des pivot_table() ou melt() de pandas.


🔀 Module 6 – PIVOT & UNPIVOT
#


🎯 Objectifs
#

À la fin du module, tu sauras :

  • Transformer des lignes en colonnes (PIVOT)
  • Aplatir des colonnes en lignes (UNPIVOT)
  • Réaliser manuellement un pivot si la fonction PIVOT n’existe pas dans ton SGBD
  • Appliquer ça à des cas concrets d’analyse

🔄 1. Pourquoi pivoter ?
#

  • Table longuetable large : voir chaque mois en colonne
  • Préparer un jeu de données pour analyse, reporting, visualisation
  • Se rapprocher de la structure utilisateur-friendly

📌 2. PIVOT (lignes → colonnes)
#

La syntaxe dépend des SGBD. Voici 3 méthodes :


✅ Méthode 1 – PIVOT natif (ex : SQL Server, DuckDB, Oracle)
#

SELECT *
FROM (
  SELECT client_id, mois, montant
  FROM ventes
) 
PIVOT (
  SUM(montant)
  FOR mois IN ('2024-01', '2024-02', '2024-03')
);

💡 Résultat : 1 ligne par client_id, avec une colonne par mois.


✅ Méthode 2 – via CASE WHEN (portable, fonctionne partout)
#

SELECT
  client_id,
  SUM(CASE WHEN mois = '2024-01' THEN montant END) AS janv,
  SUM(CASE WHEN mois = '2024-02' THEN montant END) AS fev,
  SUM(CASE WHEN mois = '2024-03' THEN montant END) AS mars
FROM ventes
GROUP BY client_id;

🔁 Très utile quand PIVOT n’est pas dispo (comme sur SQLite ou MySQL <8).


📌 3. UNPIVOT (colonnes → lignes)
#

Moins courant, mais utile pour :

  • Transformer une table large (ex : 1 colonne par mois) en longue
  • Préparer une table pour des agrégations, ou du machine learning

✅ UNPIVOT explicite (ex : SQL Server, DuckDB)
#

SELECT *
FROM ventes
UNPIVOT (
  montant FOR mois IN (janv, fev, mars)
);

✅ UNPIVOT manuel avec UNION ALL (portable)
#

SELECT client_id, '2024-01' AS mois, janv AS montant FROM ventes
UNION ALL
SELECT client_id, '2024-02', fev FROM ventes
UNION ALL
SELECT client_id, '2024-03', mars FROM ventes;

🧯 4. Pièges à éviter
#

⚠️ Piège✅ Solution
Trop de colonnes générées (pivot dynamique)Filtrer les valeurs ou faire un PIVOT dynamique côté code
Valeurs NULL après pivotUtiliser COALESCE(..., 0)
Mauvais agrégat (SUM, COUNT, etc.)Bien préciser dans la clause PIVOT(...)

🏋️‍♂️ 5. Exercices
#

Exo 1 – Transformer une table de ventes (client_id, mois, montant) pour avoir une colonne par mois
#

Exo 2 – Revenir à une table longue (client_id, mois, montant) depuis une table avec colonnes janv, fev, mars
#

Exo 3 – Créer un tableau croisé dynamique produit x mois avec SUM(montant) en valeur
#


🧰 6. Test rapide dans DuckDB (Python)
#

duckdb.sql("""
SELECT *
FROM (
  SELECT client_id, mois, montant
  FROM ventes
)
PIVOT (
  SUM(montant)
  FOR mois IN ('2024-01', '2024-02', '2024-03')
)
""").df()

📚 7. Ressources utiles
#

Thibault Clément - Intechnia
Auteur
Thibault Clément - Intechnia
Data scientist
SQL - Cet article fait partie d'une série.
Partie 6: Cet article