PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Solicitação de consulta de transposição de tabela cruzada


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:

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:

Observe também que o próximo Postgres 9.5 (atualmente beta) apresenta um Cláusula SQL para ROLLUP .
Relacionado: