A dificuldade especial é que seus dados não estão prontos para tabulação cruzada. Você precisa de dados no formato row_name , categoria , valor . Você pode obter isso com um
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;
Mas um
LATERAL
inteligente query só precisa de uma única varredura de tabela e será mais 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:
- Qual é a diferença entre LATERAL e uma subconsulta no PostgreSQL?
- SELECT DISTINCT em várias colunas
Usando a forma simples de
crosstab()
com 1 parâmetro com 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);
Liste os nomes dos países em ordem alfabética decrescente (como em sua demonstração). Isso também pressupõe que todas as métricas estejam definidas
NOT NULL
. Se um ou ambos não forem o caso, use o formulário de 2 parâmetros:
Adicionar "cumulação"
Ou seja totais 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'
é um rótulo arbitrário, que deve ser classificado por último em ordem alfabética (ou você precisa da forma de 2 parâmetros de crosstab()
). Se você tem lotes de colunas de métricas, convém construir a string de consulta dinamicamente. Relacionado:
- Como realizar a mesma agregação em todas as colunas, sem listar as colunas?
- Executando consultas dinamicamente em PL/ pgSQL
Observe também que o próximo Postgres 9.5 (atualmente beta) apresenta um Cláusula SQL para
ROLLUP
.Relacionado: