Ještě jednou, pro více než jen několik "datových typů" doporučuji použít crosstab()
:
SELECT * FROM crosstab(
$$SELECT DISTINCT ON (1, 2)
'max' AS "type", data_type, val
FROM tbl
ORDER BY 1, 2, val DESC$$
,$$VALUES ('Final Fantasy'), ('Quake 3'), ('World of Warcraft')$$)
AS x ("type" text, "Final Fantasy" int, "Quake 3" int, "World of Warcraft" int)
Vrátí:
type | Final Fantasy | Quake 3 | World of Warcraft
-----+---------------+---------+-------------------
max | 500 | 1500 | 1200
Další vysvětlení základů:
PostgreSQL Crosstab Query
Dynamické řešení
Ošemetná věc je udělat to zcela dynamickým :aby to fungovalo pro
- neznámé číslo sloupců (v tomto případě datové_typy)
- s neznámými jmény (opět data_types)
Alespoň typ je dobře známé:integer
v tomto případě.
Stručně řečeno:to není možné se současným PostgreSQL (včetně 9.3). Existují aproximace s polymorfními typy a způsoby, jak obejít omezení pomocí polí nebo typů hstore. Může to být pro vás dost dobré. Ale to přísně není možné získat výsledek s jednotlivými sloupci v jediném SQL dotazu. SQL je velmi rigidní, pokud jde o typy, a chce vědět, co očekávat.
Nicméně , lze to provést pomocí dvou dotazy. První vytvoří skutečný dotaz, který se má použít. Na základě výše uvedeného jednoduchého případu:
SELECT $f$SELECT * FROM crosstab(
$$SELECT DISTINCT ON (1, 2)
'max' AS "type", data_type, val
FROM tbl
ORDER BY 1, 2, val DESC$$
,$$VALUES ($f$ || string_agg(quote_literal(data_type), '), (') || $f$)$$)
AS x ("type" text, $f$ || string_agg(quote_ident(data_type), ' int, ') || ' int)'
FROM (SELECT DISTINCT data_type FROM tbl) x
Tím se vygeneruje dotaz, který skutečně potřebujete. Spusťte druhý v rámci stejné transakce abyste se vyhnuli problémům se souběhem.
Všimněte si strategického použití quote_literal()
a quote_ident()
dezinfikovat všechny druhy nelegálních (pro sloupce) názvů a zabránit vkládání SQL .
Nenechte se zmást několika vrstvami dolarových kotací. To je nezbytné pro vytváření dynamických dotazů. Řekl jsem to co nejjednodušší.