Alguém sabe como criar consultas de referência cruzada no PostgreSQL?
Por exemplo, tenho a seguinte tabela:
Section Status Count
A Active 1
A Inactive 2
B Active 4
B Inactive 5
Gostaria que a consulta retornasse a seguinte tabela de referência cruzada:
Section Active Inactive
A 1 2
B 4 5
Isso é possível?
Respostas:
Instale o módulo adicional
tablefunc
uma vez por banco de dados, que fornece a funçãocrosstab()
. Desde o Postgres 9.1, você pode usarCREATE EXTENSION
para isso:Caso de teste aprimorado
Formulário simples - não adequado para atributos ausentes
crosstab(text)
com 1 parâmetro de entrada:Devoluções:
C
: o valor7
é preenchido para a primeira coluna. Às vezes, esse comportamento é desejável, mas não para esse caso de uso.Formulário seguro
crosstab(text, text)
com 2 parâmetros de entrada:Devoluções:
Observe o resultado correto para
C
.O segundo parâmetro pode ser qualquer consulta que retorne uma linha por atributo que corresponda à ordem da definição da coluna no final. Freqüentemente, você deseja consultar atributos distintos da tabela subjacente como esta:
Isso está no manual.
Como você precisa digitar todas as colunas em uma lista de definições de coluna de qualquer maneira (exceto as variantes predefinidas ), geralmente é mais eficiente fornecer uma lista curta em uma expressão como demonstrada:
crosstabN()
VALUES
Ou (não no manual):
Eu usei cotação em dólar para facilitar a cotação.
Você pode até produzir colunas com diferentes tipos de dados com
crosstab(text, text)
- desde que a representação de texto da coluna de valor seja uma entrada válida para o tipo de destino. Desta forma, você pode ter os atributos de diferentes tipos e saídatext
,date
,numeric
etc. para os respectivos atributos. Há um exemplo de código no final do capítulocrosstab(text, text)
no manual .db <> mexer aqui
Exemplos avançados
Gire em várias colunas usando o Tablefunc - também demonstrando "colunas extras" mencionadas
Alternativa dinâmica para girar com CASE e GROUP BY
\crosstabview
no psqlO Postgres 9.6 adicionou esse meta-comando ao seu terminal interativo padrão psql . Você pode executar a consulta que usaria como primeiro
crosstab()
parâmetro e alimentá-la\crosstabview
(imediatamente ou na próxima etapa). Gostar:Resultado semelhante ao descrito acima, mas é um recurso de representação exclusivamente do lado do cliente . As linhas de entrada são tratadas de maneira ligeiramente diferente, portanto,
ORDER BY
não é necessário. Detalhes para\crosstabview
no manual. Existem mais exemplos de código na parte inferior dessa página.Resposta relacionada no dba.SE de Daniel Vérité (o autor do recurso psql):
A resposta aceita anteriormente está desatualizada.
A variante da função
crosstab(text, integer)
está desatualizada. O segundointeger
parâmetro é ignorado. Cito o manual atual :Fundição e renomeação desnecessárias.
Falha se uma linha não tiver todos os atributos. Consulte a variante segura com dois parâmetros de entrada acima para lidar adequadamente com os atributos ausentes.
ORDER BY
é necessário na forma de um parâmetro decrosstab()
. O manual:fonte
In practice the SQL query should always specify ORDER BY 1,2 to ensure that the input rows are properly ordered
Você pode usar a
crosstab()
função do módulo adicional tablefunc - que você deve instalar uma vez por banco de dados. Desde o PostgreSQL 9.1, você pode usarCREATE EXTENSION
para isso:No seu caso, acredito que seria algo como isto:
fonte
fonte
sum()
, seria melhor usarmin()
ormax()
e noELSE
que funcionatext
também. Mas isso tem efeitos sutilmente diferentes decorosstab()
, que usa apenas o "primeiro" valor por atributo. Não importa, desde que só possa haver um. Finalmente, o desempenho também é relevante.crosstab()
é escrito em C e otimizado para a tarefa.ERROR: 42803: aggregate function calls may not be nested
Solução com agregação JSON:
fonte
Desculpe, isso não está completo porque não posso testá-lo aqui, mas pode levá-lo na direção certa. Estou traduzindo de algo que uso que faz uma consulta semelhante:
O código do qual estou trabalhando é:
que retornará um typeID, o lance de preço mais alto e o preço mais baixo solicitado e a diferença entre os dois (uma diferença positiva significaria que algo poderia ser comprado por menos do que pode ser vendido).
fonte
Crosstab
A função está disponível sob otablefunc
extensão Você precisará criar essa extensão uma vez para o banco de dados.CRIAR EXTENSÃO
tablefunc
;Você pode usar o código abaixo para criar tabela dinâmica usando a tabulação cruzada:
fonte