La dificultad especial es que sus datos no están listos para la tabulación cruzada. Necesita datos en la forma row_name , categoría , valor . Puedes obtener eso con un UNION
consulta:
SELECT 'metric1' AS metric, country_code, metric1 FROM tbl1
UNION ALL
SELECT 'metric2' AS metric, country_code, metric2 FROM tbl1
UNION ALL
SELECT 'metric3' AS metric, country_code, metric3 FROM tbl1
ORDER BY 1, 2 DESC;
Pero un LATERAL
inteligente la consulta solo necesita un escaneo de tabla y será más rápida:
SELECT x.metric, t.country_code, x.val
FROM tbl1 t
, LATERAL (VALUES
('metric1', metric1)
, ('metric2', metric2)
, ('metric3', metric3)
) x(metric, val)
ORDER BY 1, 2 DESC;
Relacionado:
- ¿Cuál es la diferencia entre LATERAL y una subconsulta en PostgreSQL?
- SELECCIONE DISTINTO en varias columnas
Usando la forma simple de crosstab()
con 1 parámetro con esta consulta como entrada:
SELECT * FROM crosstab(
$$SELECT x.metric, t.country_code, x.val
FROM tbl1 t
, LATERAL (VALUES
('metric1', metric1)
, ('metric2', metric2)
, ('metric3', metric3)
) x(metric, val)
ORDER BY 1, 2 DESC$$
)
AS ct (metric text, us int, uk int, fr int);
Enumere los nombres de los países en orden alfabético descendente (como en su demostración). Esto también supone que todas las métricas están definidas NOT NULL
.
Si uno o ambos no son el caso, utilice la forma de 2 parámetros en su lugar:
Añadir "resumen"
Es decir. totales por métrica:
SELECT * FROM crosstab(
$$SELECT x.metric, t.country_code, x.val
FROM (
TABLE tbl1
UNION ALL
SELECT 'zzz_total', sum(metric1)::int, sum(metric2)::int, sum(metric3)::int -- etc.
FROM tbl1
) t
, LATERAL (VALUES
('metric1', metric1)
, ('metric2', metric2)
, ('metric3', metric3)
) x(metric, val)
ORDER BY 1, 2 DESC$$
)
AS ct (metric text, total int, us int, uk int, fr int);
'zzz_total'
es una etiqueta arbitraria, que debe ordenarse en último lugar alfabéticamente (o necesita la forma de 2 parámetros de crosstab()
).
Si tienes muchos de columnas de métricas, es posible que desee generar la cadena de consulta dinámicamente. Relacionado:
- ¿Cómo realizar la misma agregación en cada columna, sin enumerar las columnas?
- Ejecutar consultas dinámicamente en PL/ pgSQL
También tenga en cuenta que el próximo Postgres 9.5 (actualmente beta) presenta un Cláusula SQL para ROLLUP
.
Relacionado: