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:
- Was ist der Unterschied zwischen LATERAL und einer Unterabfrage in PostgreSQL?
- SELECT DISTINCT für mehrere Spalten
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:
- Wie führe ich dieselbe Aggregation für jede Spalte durch, ohne die Spalten aufzulisten?
- Abfragen dynamisch in PL ausführen/ pgSQL
Beachten Sie auch, dass das kommende Postgres 9.5 (derzeit Beta) einen dedizierten SQL-Klausel für ROLLUP
.
Verwandt: