Aller au contenu

Pivot et Unpivot

·2 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.


🔄 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

📌 PIVOT (lignes → colonnes)
#

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

  • Méthode 1PIVOT 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 (?)).


📌 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

Voici deux manières :

  • ✅ 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;
    

🧯 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(...)

🏋️‍♂️ Exercices
#

  • Transformer une table de ventes (client_id, mois, montant) pour avoir une colonne par mois
  • Revenir à une table longue (client_id, mois, montant) depuis une table avec colonnes janv, fev, mars
  • Créer un tableau croisé dynamique produit x mois avec SUM(montant) en valeur
duckdb.sql("""
SELECT *
FROM (
  SELECT client_id, mois, montant
  FROM ventes
)
PIVOT (
  SUM(montant)
  FOR mois IN ('2024-01', '2024-02', '2024-03')
)
""").df()

📚 Ressources utiles
#

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