Jeszcze raz, dla więcej niż tylko kilku "typów danych", sugeruję użycie 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)
Zwroty:
type | Final Fantasy | Quake 3 | World of Warcraft
-----+---------------+---------+-------------------
max | 500 | 1500 | 1200
Więcej wyjaśnień podstaw:
Kwerenda krzyżowa PostgreSQL
Rozwiązanie dynamiczne
Trudną rzeczą jest sprawienie, aby to było całkowicie dynamiczne :aby to działało
- nieznany numer kolumn (w tym przypadku data_types)
- z nieznanymi nazwami (ponownie data_types)
Przynajmniej typ jest dobrze znany:integer
w tym przypadku.
W skrócie:nie jest to możliwe w obecnym PostgreSQL (w tym w wersji 9.3). Istnieją przybliżenia z typami polimorficznymi i sposoby na obejście ograniczeń za pomocą tablic lub typów hstore. Może być dla ciebie wystarczająco dobry. Ale to całkowicie niemożliwe aby uzyskać wynik z pojedynczymi kolumnami w jednym zapytaniu SQL. SQL jest bardzo sztywny co do typów i chce wiedzieć, czego się spodziewać.
Jednak , można to zrobić za pomocą dwóch zapytania. Pierwsza z nich buduje rzeczywiste zapytanie do użycia. Opierając się na powyższym prostym przypadku:
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
To generuje zapytanie, którego faktycznie potrzebujesz. Uruchom drugi w tej samej transakcji aby uniknąć problemów ze współbieżnością.
Zwróć uwagę na strategiczne użycie quote_literal()
i quote_ident()
do oczyszczania wszelkiego rodzaju niedozwolonych nazw (dla kolumn) i zapobiegania wstrzykiwaniu SQL .
Nie daj się zwieść wielu warstwom kwotowania w dolarach. Jest to niezbędne do tworzenia zapytań dynamicznych. Mówię to tak prosto, jak to tylko możliwe.