PostgreSQL: usando uma coluna calculada na mesma consulta

Estou com problemas para usar uma coluna calculada em postgres. Um código similar que funciona em SQL é dado abaixo, é possível recriar isso no PostgreSQL ?

 select cost_1, quantity_1, cost_2, quantity_2, (cost_1 * quantity_1) as total_1, (cost_2 * quantity_2) as total_2, (calculated total_1 + calculated total_2) as total_3 from data; 

No PostgreSQL um código semelhante retorna o erro que:

as colunas total_1 e total_2 não existem.

Você precisa envolver a instrução SELECT em uma tabela derivada para poder acessar o alias da coluna:

 select cost1, quantity_1, cost_2, quantity_2 total_1 + total_2 as total_3 from ( select cost_1, quantity_1, cost_2, quantity_2, (cost_1 * quantity_1) as total_1, (cost_2 * quantity_2) as total_2 from data ) t 

Não haverá qualquer penalidade de desempenho sobre isso.

(Estou realmente surpreso que sua instrução SQL original seja executada em um DBMS)

Se você não gosta de pesquisar toda a query com outerquery, você pode usar o LATERAL para calcular o intermediário total_1 e o total_2 :

 SELECT cost_1, quantity_1, cost_2, quantity_2, total_1, total_2, total_1 + total_2 AS total_3 FROM data ,LATERAL(SELECT cost_1 * quantity_1, cost_2 * quantity_2) AS s1(total_1,total_2); 

DBFiddle Demo

Saída:

 ╔═════════╦═════════════╦═════════╦═════════════╦══════════╦══════════╦═════════╗ ║ cost_1 ║ quantity_1 ║ cost_2 ║ quantity_2 ║ total_1 ║ total_2 ║ total_3 ║ ╠═════════╬═════════════╬═════════╬═════════════╬══════════╬══════════╬═════════╣ ║ 1 ║ 2 ║ 3 ║ 4 ║ 2 ║ 12 ║ 14 ║ ║ 3 ║ 5 ║ 7 ║ 9 ║ 15 ║ 63 ║ 78 ║ ║ 10 ║ 5 ║ 20 ║ 2 ║ 50 ║ 40 ║ 90 ║ ╚═════════╩═════════════╩═════════╩═════════════╩══════════╩══════════╩═════════╝ 

Como regra, há duas coisas que você precisa saber sobre a cláusula SELECT :

  • Embora seja escrito primeiro , ele é avaliado por último , com exceção da cláusula ORDER BY . É por isso que você não pode usar nenhum campo ou aliases calculados em nenhuma outra cláusula (especialmente a cláusula WHERE ), exceto na cláusula ORDER BY .
  • Cálculos na cláusula SELECT são executados em paralelo , ou pelo menos são tratados como se fossem. É por isso que você não pode usar um cálculo como parte de outro.

Então, a resposta curta é que você não pode, e isso é por design.

A exceção notável para isso é o Microsoft Access, onde você pode realmente usar cálculos em colunas subseqüentes e cláusulas WHERE . No entanto, embora isso seja conveniente, na verdade não é uma vantagem: não seguir os princípios acima é menos eficiente. Mas está tudo bem para bancos de dados de serviços leves, que é o que o Access deve ser usado.

Se você realmente quiser reutilizar os resultados calculados, precisará de uma consulta separada, na forma de uma subconsulta ou como uma expressão de tabela comum. Os CTEs são muito mais fáceis de trabalhar, pois são mais fáceis de ler.

Editar

Sem mudar o ponto da resposta original, achei que poderia acrescentar que acho que essa explicação é possivelmente um pouco mesquinha.

Os SGBDs modernos se esforçam muito para planejar e otimizar as consultas, de modo que não é mais correto, ou nunca, que a consulta seja realmente executada em uma ordem específica. Tanto quanto eu posso ver, não há razão técnica porque o otimizador não pode olhar para frente e incorporar resultados calculados na análise da consulta, mesmo que seja apenas para replace expressões.

Ah bem …

 select cost_1, quantity_1, cost_2, quantity_2, cost_1 * quantity_1 as total_1, cost_2 * quantity_2 as total_2, (cost_1 * quantity_1 + cost_2 * quantity_2) as total_3 from data; 

Você está tentando usar aliases de coluna em uma expressão. Se um sistema permite que você faça isso, é apenas um açúcar sintático. Isso deve funcionar em qualquer dialeto do SQL.

 select cost_1 ,quantity_1 ,cost_2 ,quantity_2 ,cost_1 * quantity_1 as total_1 ,cost_2 * quantity_2 as total_2 ,(cost_1 * quantity_1) + (cost_2 * quantity_2) as total_3 from data; 
Intereting Posts