2012-01-12 20 views
23

Tengo problemas para usar una columna calculada en postgres. Un código similar que funciona en SQL se da a continuación, ¿es posible recrear esto en PostgreSQL?PostgreSQL: utilizando una columna calculada en la misma consulta

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; 

En PostgreSQL un código similar devuelve el error que:

la TOTAL_1 columna y TOTAL_2 no existen.

+0

posible duplicado de [PostgreSQL Vistas: Hacer referencia a un campo calculado en otro campo calculado] (http://stackoverflow.com/questions/2385791/postgresql-views-referencing-one-calculated-field -in-another-calculate-field) –

+2

'funciona en SQL'? Nos ha mostrado SQL y luego ha declarado que no funciona. Entonces, ¿qué quieres decir con "* en SQL *"? –

Respuesta

-2

Está intentando usar alias de columna en una expresión. Si un sistema te permite hacer eso, es solo azúcar sintáctica. Esto debería funcionar en cualquier dialecto 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; 
29

Usted necesita para dar la instrucción SELECT en una tabla derivada con el fin de poder acceder al alias de columna:

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 

No habrá ninguna pérdida de rendimiento en eso.

(estoy realmente sorprendido de que la instrucción SQL original, funciona en absoluto en un DBMS)

+2

La publicación original se parece al PROC SQL de SAS que permite este – Andrew

+0

Me gustaría tener una definición de let ... = .... como en Haskell aquí para definir un cálculo local en lugar de una subconsulta. Eso seria genial. Sin embargo, ¡gracias por su buena respuesta! – Hartmut

+0

¿Cuál es la ventaja/desventaja de envolver select statement y no usar CTE por ejemplo? Gracias :) – Davita

12

Si no te gusta wraping consulta completa con outerquery, se puede usar para calcular LATERAL intermedia total_1 y 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); 

SqlFiddleDemo

Salida:

╔═════════╦═════════════╦═════════╦═════════════╦══════════╦══════════╦═════════╗ 
║ 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 ║ 
╚═════════╩═════════════╩═════════╩═════════════╩══════════╩══════════╩═════════╝ 
+2

Oh, bien. TIL. Esto es mucho más agradable en algunos casos, incluido el mío, que está creando una vista que hace muchas capas de referencia a los cálculos anteriores. Alinear cálculos repetidos es propenso a errores y las subconsultas de anidamiento tenían como 9 niveles de anidación para mí. La versión 'LATERAL' es mucho más fácil de seguir y mantener. –

6

Como regla general, hay una de dos cosas que hay que saber sobre el SELECT cláusula:

  • Aunque está escrito primera, se evalúa última, con a excepción de la cláusula ORDER BY. Esta es la razón por la cual no puede usar ningún campo calculado o alias en ninguna otra cláusula (particularmente la WHERE) excepto en la cláusula ORDER BY.
  • Los cálculos en la cláusula SELECT se realizan en paralelo, o al menos se manejan como si fueran. Es por eso que no puede usar un cálculo como parte de otro.

Por lo tanto, la respuesta corta es que no se puede, y eso es por diseño.

La notable excepción a esto es Microsoft Access, donde puede utilizar cálculos en columnas posteriores y WHERE cláusulas. Sin embargo, aunque es conveniente, en realidad no es una ventaja: no seguir los principios anteriores es menos eficiente. Pero está bien para bases de datos livianas, que es para lo que se supone que se debe usar Access.

Si realmente desea volver a utilizar los resultados calculados, necesitará una consulta por separado, ya sea en forma de una sub consulta o como una Expresión de tabla común. Los CTE son mucho más fáciles de trabajar, ya que son más claros de leer.

Editar

Sin cambiar el punto de la respuesta original, pensé que podría añadir que creo que esta explicación es posiblemente un poco mal intencionada.

Los DBMS modernos hacen un gran esfuerzo en la planificación y optimización de consultas, por lo que ya no es correcto, si es que alguna vez, que la consulta se ejecuta realmente en un orden particular. Por lo que puedo ver, no hay técnico por lo que el optimizador no pudo mirar hacia el futuro e incorporar resultados calculados en el análisis de la consulta, incluso si solo es para sustituir expresiones.

Oh, bueno ...

Cuestiones relacionadas