De speciale moeilijkheid is dat uw gegevens niet klaar zijn voor kruistabellen. U hebt gegevens nodig in de vorm row_name , categorie , waarde . Je kunt dat krijgen met een UNION
vraag:
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;
Maar een slimme LATERAL
query heeft slechts een enkele tabelscan nodig en zal sneller zijn:
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;
Gerelateerd:
- Wat is het verschil tussen LATERAL en een subquery in PostgreSQL?
- SELECTEER DISTINCT op meerdere kolommen
Gebruik de eenvoudige vorm van crosstab()
met 1 parameter met deze vraag als invoer:
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);
Lijst landnamen in alfabetisch aflopende volgorde (zoals in uw demo). Dit veronderstelt ook dat alle statistieken zijn gedefinieerd NOT NULL
.
Als een of beide niet het geval is, gebruikt u in plaats daarvan het 2-parameterformulier:
Toevoegen "rollup"
D.w.z. totalen per statistiek:
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'
is een willekeurig label, dat als laatste alfabetisch moet worden gesorteerd (of je hebt de 2-parametervorm van crosstab()
nodig ).
Als u veel heeft van metrische kolommen, wilt u misschien de querytekenreeks dynamisch opbouwen. Gerelateerd:
- Hoe kan ik dezelfde aggregatie uitvoeren op elke kolom, zonder de kolommen op te sommen?
- query's dynamisch uitvoeren in PL/ pgSQL
Merk ook op dat de aanstaande Postgres 9.5 (momenteel bèta) een speciale SQL-clausule voor ROLLUP
.
Gerelateerd: