PIVOT / UNPIVOT (lignes↔colonnes)
Oracle
-- Turn sales by month into columns
SELECT * FROM (
SELECT month, amount FROM sale
)
PIVOT (SUM(amount) FOR month IN ('Jan' AS jan, 'Feb' AS feb, 'Mar' AS mar));
-- UNPIVOT: turn columns back into rows
SELECT product, month, amount
FROM sale_wide
UNPIVOT (amount FOR month IN (jan AS 'Jan', feb AS 'Feb'));PIVOT transforme les valeurs distinctes des lignes en colonnes (tableau croisé), et UNPIVOT retransforme les colonnes en lignes ; utilisé dans les tables de synthèse/rapports. Oracle offre des opérateurs PIVOT/UNPIVOT intégrés depuis 11g ; la liste des colonnes doit être statique (les colonnes dynamiques nécessitent PIVOT XML ou du code).
PostgreSQL
-- The tablefunc extension for crosstab
CREATE EXTENSION IF NOT EXISTS tablefunc;
SELECT * FROM crosstab(
'SELECT product, month, amount FROM sale ORDER BY 1,2'
) AS ct(product text, jan numeric, feb numeric, mar numeric);
-- Without an extension: conditional aggregation
SELECT product,
SUM(amount) FILTER (WHERE month = 'Jan') AS jan,
SUM(amount) FILTER (WHERE month = 'Feb') AS feb
FROM sale GROUP BY product;PostgreSQL n'a pas d'opérateur PIVOT intégré. Il existe deux méthodes : la fonction crosstab() de l'extension tablefunc, ou l'agrégation conditionnelle portable (SUM(...) FILTER (WHERE ...) ou avec CASE). La clause FILTER est une technique de pivot élégante propre à PostgreSQL.
MySQL
-- There is no PIVOT; conditional aggregation with manual CASE
SELECT product,
SUM(CASE WHEN month = 'Jan' THEN amount ELSE 0 END) AS jan,
SUM(CASE WHEN month = 'Feb' THEN amount ELSE 0 END) AS feb,
SUM(CASE WHEN month = 'Mar' THEN amount ELSE 0 END) AS mar
FROM sale
GROUP BY product;MySQL/MariaDB n'ont pas d'opérateur PIVOT/UNPIVOT ; un tableau croisé se construit à la main avec GROUP BY plus un SUM(CASE WHEN ... THEN ... END) pour chaque colonne cible. Si les colonnes sont dynamiques, la requête est générée sous forme de chaîne avec un prepared statement.
SQL Server
SELECT * FROM (
SELECT product, month, amount FROM sale
) src
PIVOT (
SUM(amount) FOR month IN ([Jan], [Feb], [Mar])
) pvt;
-- Converting back with UNPIVOT is also supportedSQL Server prend en charge nativement les opérateurs PIVOT et UNPIVOT depuis 2005. La liste des colonnes du PIVOT est donnée sous forme de valeurs statiques entre crochets ; pour des colonnes dynamiques, la requête est construite en SQL dynamique. Pour de petites synthèses, l'agrégation conditionnelle (CASE) est une alternative.
MongoDB
// PIVOT equivalent: conditional aggregation inside $group
db.sale.aggregate([
{ $group: {
_id: "$product",
jan: { $sum: { $cond: [ { $eq: ["$month", "Jan"] }, "$amount", 0 ] } },
feb: { $sum: { $cond: [ { $eq: ["$month", "Feb"] }, "$amount", 0 ] } }
} }
])MongoDB n'a pas d'opérateur PIVOT ; un tableau croisé se construit dans l'étape $group avec $sum + $cond (agrégation conditionnelle) pour chaque colonne cible. Pour le sens inverse (UNPIVOT), les champs sont développés en lignes avec $objectToArray et $unwind.
Redis
# Not applicable: Redis has no pivot/cross tab.Redis n'a pas de notion de rotation lignes/colonnes. Les synthèses/tableaux croisés se calculent côté application ; les synthèses fréquemment demandées peuvent être précalculées et stockées dans des champs de Hash (un champ par colonne). FT.AGGREGATE de RediSearch peut faire de l'agrégation groupée, mais ce n'est pas un vrai pivot.
Elasticsearch
# Closest equivalent: nested terms aggregations
GET sale/_search
{
"size": 0,
"aggs": { "product": { "terms": { "field": "product" },
"aggs": { "month": { "terms": { "field": "month" },
"aggs": { "total": { "sum": { "field": "amount" } } } } } }
}Elasticsearch n'a pas d'opérateur PIVOT ; une synthèse croisée se construit avec des agrégations terms imbriquées (clé externe / clé interne), le résultat revient sous forme de buckets imbriqués plutôt que de colonnes et est mis en tableau côté client. Un job transform peut produire un index cible groupé, de type pivot.