PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Richiesta di query di trasposizione a campi incrociati

La difficoltà speciale è che i tuoi dati non sono pronti per la tabulazione incrociata. Hai bisogno dei dati nel modulo nome_riga , categoria , valore . Puoi ottenerlo con un UNION domanda:

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;

Ma un intelligente LATERAL query richiede solo una scansione di una singola tabella e sarà più veloce:

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;

Correlati:

Usando la semplice forma di crosstab() con 1 parametro con questa query come input:

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);

Elenca i nomi dei paesi in ordine alfabetico decrescente (come nella tua demo). Ciò presuppone anche che tutte le metriche siano definite NOT NULL .

Se uno o entrambi non sono il caso, utilizzare invece il modulo a 2 parametri:

Aggiungi "rollup"

Cioè. totali per metrica:

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' è un'etichetta arbitraria, che deve essere ordinata per ultima in ordine alfabetico (oppure è necessaria la forma a 2 parametri di crosstab() ).

Se hai lotti delle colonne delle metriche, potresti voler creare la stringa di query in modo dinamico. Correlati:

Si noti inoltre che il prossimo Postgres 9.5 (attualmente beta) introduce un Clausola SQL per ROLLUP .
Correlati: