PIVOT et UNPIVOT en Oracle : tableaux croisés (exemples)

PIVOT transforme des lignes en colonnes (tableau croisé), UNPIVOT fait l'inverse. Syntaxe Oracle, alternative SUM+CASE et exemples concrets.

Illustration : PIVOT et UNPIVOT Oracle

PIVOT en Oracle transforme des lignes en colonnes (pour un tableau croisé), et UNPIVOT fait l’inverse (colonnes en lignes). C’est l’outil idéal pour produire des rapports type « CA par mois en colonnes » à partir de données stockées en lignes. Voici la syntaxe des deux, avec exemples.

Publicité

Le problème que PIVOT résout

Vos ventes sont stockées en lignes (un mois par ligne), mais vous voulez un tableau avec un mois par colonne. C’est exactement le rôle de PIVOT.

PIVOT : lignes → colonnes

SELECT * FROM (
  SELECT vendeur, mois, montant FROM ventes
)
PIVOT (
  SUM(montant)
  FOR mois IN ('Jan' AS jan, 'Fev' AS fev, 'Mar' AS mar)
);

Résultat : une ligne par vendeur, avec les colonnes JAN, FEV, MAR. Décomposons :

  • SUM(montant) : l’agrégat à afficher dans les cases.
  • FOR mois IN (...) : les valeurs de mois qui deviennent des colonnes.
  • Les autres colonnes de la sous-requête (vendeur) forment les lignes.

⚠️ Astuce importante : ne mettez dans la sous-requête que les colonnes utiles (vendeur, mois, montant) ; toute colonne supplémentaire crée des lignes en trop.

L’alternative manuelle : SUM + CASE

Avant Oracle 11g (ou pour plus de contrôle), on pivote avec CASE :

SELECT vendeur,
  SUM(CASE WHEN mois='Jan' THEN montant END) AS jan,
  SUM(CASE WHEN mois='Fev' THEN montant END) AS fev,
  SUM(CASE WHEN mois='Mar' THEN montant END) AS mar
FROM ventes GROUP BY vendeur;

UNPIVOT : colonnes → lignes

L’inverse : transformer des colonnes (jan, fev, mar) en lignes (mois, montant).

SELECT vendeur, mois, montant
FROM ventes_pivot
UNPIVOT (
  montant FOR mois IN (jan AS 'Jan', fev AS 'Fev', mar AS 'Mar')
);

Pratique pour « normaliser » un tableau croisé importé d’Excel.

PIVOT avec plusieurs agrégats

SELECT * FROM ventes
PIVOT (
  SUM(montant) AS total, COUNT(*) AS nb
  FOR mois IN ('Jan' AS jan, 'Fev' AS fev)
);
-- colonnes : JAN_TOTAL, JAN_NB, FEV_TOTAL, FEV_NB

Limite : les colonnes doivent être connues

PIVOT exige de lister les valeurs (les mois) à l’avance. Pour un nombre de colonnes dynamique (inconnu), il faut générer la requête en SQL dynamique ou utiliser PIVOT XML.

FAQ

PIVOT existe depuis quelle version ?

Depuis Oracle 11g. Avant, on utilisait la technique SUM + CASE, qui reste valable partout.

Pourquoi j’ai des lignes en double après un PIVOT ?

Une colonne « parasite » est restée dans la sous-requête. Ne sélectionnez que les colonnes de regroupement + la colonne pivotée + la valeur agrégée.

Peut-on pivoter sur des colonnes dynamiques ?

Pas directement : il faut construire la liste des colonnes en SQL dynamique, ou utiliser PIVOT (... XML) qui renvoie un résultat XML.

Un nouveau tutoriel SQL par semaine

Nous ne spammons pas ! Consultez notre politique de confidentialité pour plus d’informations.

Publicité

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Cours SQL & Oracle — 100% gratuitVoir les cours →