Ancora una volta, per più di alcuni "tipi di dati", suggerisco di utilizzare 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)
Resi:
type | Final Fantasy | Quake 3 | World of Warcraft
-----+---------------+---------+-------------------
max | 500 | 1500 | 1200
Ulteriori spiegazioni per le nozioni di base:
Query a campi incrociati PostgreSQL
Soluzione dinamica
La cosa difficile è rendere questo completamente dinamico :per farlo funzionare
- un numero sconosciuto di colonne (data_types in questo caso)
- con nomi sconosciuti (di nuovo tipi_dati)
Almeno il tipo è noto:integer
in questo caso.
In breve:questo non è possibile con l'attuale PostgreSQL (incluso 9.3). Esistono approssimazioni con tipi polimorfici e modi per aggirare le restrizioni con array o tipi hstore. Potrebbe essere abbastanza buono per te. Ma è rigorosamente impossibile per ottenere il risultato con singole colonne in una singola query SQL. SQL è molto rigido sui tipi e vuole sapere cosa aspettarsi in cambio.
Tuttavia , può essere fatto con due interrogazioni. Il primo crea la query effettiva da utilizzare. Basandosi sul semplice caso di cui sopra:
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
Questo genera la query di cui hai effettivamente bisogno. Esegui il secondo all'interno della stessa transazione per evitare problemi di concorrenza.
Nota l'uso strategico di quote_literal()
e quote_ident()
per disinfettare tutti i tipi di nomi illegali (per colonne) e prevenire SQL injection .
Non lasciarti confondere da più livelli di quotazione del dollaro. È necessario per creare query dinamiche. Lo metto il più semplice possibile.