Eu fiz uma pergunta aqui: /programming/43807566/how-to-divide-two-values-from-the-same-column-but-at-different-rows
sobre como dividir valores da mesma tabela, na mesma coluna, mas em linhas diferentes. Agora eu tenho o problema em que tenho mais numeradores e denominadores (com diferentes uns
). Ainda é self join
uma boa maneira de resolver esse problema com o Postgres ou existem soluções melhores?
Exemplo:
| postcode | value | uns |
|----------|-------|-----|
| AA | 40 | 53 |
| BB | 20 | 53 |
| AA | 10 | 54 |
| AA | 20 | 55 |
| AA | 10 | 56 |
| AA | 30 | 57 |
| AA | 50 | 58 |
| BB | 10 | 54 |
| BB | 10 | 55 |
| BB | 70 | 56 |
| BB | 80 | 57 |
| BB | 10 | 58 |
O resultado deve ser:
| postcode | formula |
|----------|------------|
| AA | 18.888... |
| BB | 14.375 |
Onde o valor é agrupado por código postal e a fórmula é (valor com uns):
(V53 * V56 + V54 * V57 + V55 * V58) / (V56 + V57 + V58)
Preste atenção para evitar eventual divisão por zero. A fórmula pode ser ainda mais complexa, mas esse é um bom exemplo.
postgresql
pivot
computed-column
Aleatória
fonte
fonte
uns
nomes das colunas se tornem - a partir daí, qualquer fórmula que use os valores se tornará viável. A fórmula será codificada ou derivada dinamicamente de alguma forma?Respostas:
Este é um problema de pivô / crosstab em sua essência, como Michael já diagnosticou com precisão.
Se você não está familiarizado com o
tablefunc
módulo no Postgres, leia as instruções básicas aqui:A consulta se torna simples e muito rápida (mais rápida que outras soluções apresentadas aqui):
NULLIF
para impedir a divisão por zero.dbfiddle aqui
fonte
Você pode agregar todos os pares uns / value em um objeto JSON e usá-lo para acessar os valores UNS por nome. Isso requer alguma conversão, já que os valores só podem ser extraídos como texto do objeto JSON, mas a fórmula é muito semelhante à sua descrição:
Dividi a agregação, a avaliação do denominador e divisor e a divisão final em três etapas para torná-lo mais legível.
Exemplo online: http://rextester.com/IZYT54566
Você pode simplificar a fórmula criando uma função:
fonte
O padrão PIVOT funcionaria para isso. Ele converte os valores das linhas em colunas em uma única linha, de acordo com sua chave comum. Existem algumas maneiras de implementar isso. Alguns exigem apenas uma única verificação de tabela.
Após o PIVOT, você teria uma tabela com uma linha por código postal e uma coluna por valor. O restante da consulta seria gravado como se referenciasse uma única tabela.
fonte
Supondo que
(postcode, uns)
sejamUNIQUE
(provavelmente, um PK), o padrão PIVOT, como já comentado por @ michael-green, pode ser implementado de forma portável, usando a seguinte consulta:Verifique no SQLFiddle .
fonte
Supondo que
(postcode, uns)
sejaUNIQUE
(provavelmente, um PK), provavelmente o caminho mais simples , provavelmente o mais portátil, embora provavelmente não seja o ideal: use o número de sub-seleções necessário :Verifique no SQLFiddle .
fonte