Den speciella svårigheten är att dina data inte är redo för korstabulering. Du behöver data i formen radnamn , kategori , värde . Du kan få det med en UNION
fråga:
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;
Men en smart LATERAL
fråga behöver bara en enda tabellskanning och kommer att vara snabbare:
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;
Relaterat:
Med den enkla formen crosstab()
med 1 parameter med denna fråga som indata:
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);
Lista landsnamn i alfabetiskt fallande ordning (som i din demo). Detta förutsätter också att alla mätvärden är definierade NOT NULL
.
Om en eller båda inte är fallet, använd istället formuläret med två parametrar:
Lägg till "samlad"
d.v.s. totalt per mätvärde:
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'
är en godtycklig etikett som måste sorteras sist i alfabetisk ordning (eller så behöver du 2-parametersformen crosstab()
).
Om du har massor av statistikkolumner, kanske du vill bygga frågesträngen dynamiskt. Relaterat:
- Hur gör man samma aggregering på varje kolumn, utan att lista kolumnerna?
- Köra frågor dynamiskt i PL/ pgSQL
Observera också att den kommande Postgres 9.5 (för närvarande beta) introducerar en dedikerad SQL-sats för ROLLUP
.
Relaterat: