Mais uma vez, para mais do que apenas alguns "tipos de dados", sugiro usar
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)
Devoluções:
type | Final Fantasy | Quake 3 | World of Warcraft
-----+---------------+---------+-------------------
max | 500 | 1500 | 1200
Mais explicações para o básico:
Consulta de tabela cruzada PostgreSQL
Solução dinâmica
O complicado é tornar isso completamente dinâmico :para fazê-lo funcionar para
- um número desconhecido de colunas (data_types neste caso)
- com nomes desconhecidos (data_types novamente)
Pelo menos o tipo é bem conhecido:
integer
nesse caso. Resumindo:isso não é possível com o PostgreSQL atual (incluindo 9.3). Existem aproximações com tipos polimórficos e formas de contornar as restrições com arrays ou tipos hstore. Pode ser bom o suficiente para você. Mas é estritamente impossível para obter o resultado com colunas individuais em uma única consulta SQL. O SQL é muito rígido em relação aos tipos e quer saber o que esperar de volta.
No entanto , isso pode ser feito com dois consultas. O primeiro cria a consulta real a ser usada. Com base no caso simples acima:
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
Isso gera a consulta que você realmente precisa. Execute o segundo dentro da mesma transação para evitar problemas de simultaneidade.
Observe o uso estratégico de
quote_literal()
e quote_ident()
para limpar todos os tipos de nomes ilegais (para colunas) e impedir a injeção de SQL . Não se confunda com várias camadas de cotação de dólares. Isso é necessário para criar consultas dinâmicas. Coloquei o mais simples possível.