78

我在使用 postgres 中的计算列时遇到问题。下面给出了在 SQL 中工作的类似代码,是否可以在其中重新创建它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;

PostgreSQL类似的代码中返回以下错误:

列 total_1 和 total_2 不存在。

4

5 回答 5

68

您需要将 SELECT 语句包装到派生表中才能访问列别名:

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

不会有任何性能损失。

(我真的很惊讶你原来的 SQL 语句在 DBMS 中运行)

于 2012-01-12T20:35:40.357 回答
52

如果您不喜欢用外部查询包装整个查询,您可以使用LATERAL计算中间total_1total_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 演示

输出:

╔═════════╦═════════════╦═════════╦═════════════╦══════════╦══════════╦═════════╗
║ 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 ║
╚═════════╩═════════════╩═════════╩═════════════╩══════════╩══════════╩═════════╝
于 2016-04-10T13:13:28.230 回答
21

通常,您需要了解有关该SELECT子句的两件事:

  • 尽管它是first编写的,但它是last评估的,除了ORDER BY从句。这就是为什么您不能在该子句之外的任何其他子句(特别是该WHERE子句)中使用任何计算字段或别名的原因。ORDER BY
  • SELECT子句中的计算是并行执行的,或者至少是像这样处理的。这就是为什么您不能将一个计算用作另一个计算的一部分。

所以,简短的回答是你不能,这是设计使然。

值得注意的例外是 Microsoft Access,您确实可以在后续列和WHERE子句中使用计算。然而,虽然这很方便,但实际上并不是一个优势:不遵循上述原则效率较低。但是对于轻型数据库来说没问题,这就是 Access 应该用于的。

如果您真的想重用计算结果,您将需要一个单独的查询,可以是子查询的形式,也可以是公用表表达式。CTE 更易于使用,因为它们更易于阅读。

编辑

以下是使用计算列可能导致混淆的示例。在澳大利亚,我们以厘米为单位测量身高,但仍有一些地方使用古代英寸(1 英寸 = 2.54 厘米)。

SELECT
    id,
    height/2.54 as height, -- cm -> in
    case when height>175 then 'tall' else '' end as comment
FROM people;

这里CASE仍然使用原始height值。

于 2017-03-10T07:17:53.220 回答
1
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;
于 2018-07-20T23:13:44.480 回答
-4

您正在尝试在表达式中使用列别名。如果一个系统允许你这样做,那只是语法糖。这应该适用于任何 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;
于 2012-01-12T18:33:40.740 回答