PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Kreuztabellentranspositionsabfrageanforderung

Die besondere Schwierigkeit besteht darin, dass Ihre Daten nicht bereit für die Kreuztabelle sind. Sie benötigen Daten in der Form row_name , Kategorie , Wert . Das bekommst du mit einer UNION Abfrage:

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;

Aber ein pfiffiger LATERAL Die Abfrage benötigt nur einen einzigen Tabellenscan und ist schneller:

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;

Verwandte:

Verwenden der einfachen Form von crosstab() mit 1 Parameter mit dieser Abfrage als Eingabe:

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

Listen Sie die Ländernamen in alphabetisch absteigender Reihenfolge auf (wie in Ihrer Demo). Dies setzt auch voraus, dass alle Metriken NOT NULL definiert sind .

Wenn einer oder beide nicht der Fall sind, verwenden Sie stattdessen die 2-Parameter-Form:

Fügen Sie "Rollup" hinzu

Dh Summen pro Metrik:

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' ist ein beliebiges Label, das alphabetisch als letztes sortiert werden muss (oder Sie benötigen die 2-Parameter-Form von crosstab()). ).

Wenn Sie viele haben von Metrikspalten möchten Sie die Abfragezeichenfolge möglicherweise dynamisch erstellen. Verwandte:

Beachten Sie auch, dass das kommende Postgres 9.5 (derzeit Beta) einen dedizierten SQL-Klausel für ROLLUP .
Verwandt: