PIVOT / UNPIVOT (filas↔columnas)
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 convierte los valores distintos de las filas en columnas (una tabla cruzada) y UNPIVOT vuelve a convertir las columnas en filas; se usan en tablas resumen/de informes. Oracle ofrece los operadores PIVOT/UNPIVOT integrados desde 11g; la lista de columnas debe ser estática (las columnas dinámicas requieren PIVOT XML o código).
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 no tiene un operador PIVOT integrado. Hay dos vías: la función crosstab() de la extensión tablefunc, o la agregación condicional portable (SUM(...) FILTER (WHERE ...) o con CASE). La cláusula FILTER es una técnica de pivot elegante y específica de 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 no tienen operador PIVOT/UNPIVOT; una tabla cruzada se construye a mano con GROUP BY más un SUM(CASE WHEN ... THEN ... END) por cada columna de destino. Si las columnas son dinámicas, la consulta se genera como cadena con 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 admite de forma nativa los operadores PIVOT y UNPIVOT desde 2005. La lista de columnas de PIVOT se indica como valores estáticos entre corchetes; para columnas dinámicas la consulta se construye con SQL dinámico. Para resúmenes pequeños, la agregación condicional (CASE) es una alternativa.
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 no tiene operador PIVOT; una tabla cruzada se construye en la etapa $group con $sum + $cond (agregación condicional) por cada columna de destino. Para el sentido inverso (UNPIVOT), los campos se expanden en filas con $objectToArray y $unwind.
Redis
# Not applicable: Redis has no pivot/cross tab.Redis no tiene el concepto de rotar filas y columnas. Los resúmenes/tablas cruzadas se calculan en la aplicación; los resúmenes solicitados con frecuencia se pueden precalcular y almacenar en campos de un Hash (un campo por columna). FT.AGGREGATE de RediSearch puede hacer agregaciones agrupadas, pero no es un pivot real.
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 no tiene operador PIVOT; un resumen cruzado se construye con terms aggregations anidadas (clave externa / clave interna); el resultado vuelve como buckets anidados en lugar de columnas y se convierte en tabla en el cliente. Un transform job puede generar un índice de destino agrupado, similar a un pivot.