PostgreSQL:在同一查询中使用计算列

发布于 2024-12-26 12:13:22 字数 405 浏览 0 评论 0原文

我在使用 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不存在。

I am having trouble using a calculated column in postgres. A similar code which works in SQL is given below, is it possible to recreate this in 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;

In PostgreSQL a similar code returns the error that:

the column total_1 and total_2 do not exist.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

救赎№ 2025-01-02 12:13:22

您需要将 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 中运行)

You need to wrap the SELECT statement into a derived table in order to be able to access the column alias:

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

There won't be any performance penalty on that.

(I'm really surprised that your original SQL statement runs at all in a DBMS)

萧瑟寒风 2025-01-02 12:13:22

如果您不喜欢用外部查询包装整个查询,可以使用 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 ║
╚═════════╩═════════════╩═════════╩═════════════╩══════════╩══════════╩═════════╝

If you don't like wraping entire query with outerquery, you could use LATERAL to calculate intermediate total_1 and 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

Output:

╔═════════╦═════════════╦═════════╦═════════════╦══════════╦══════════╦═════════╗
║ 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 ║
╚═════════╩═════════════╩═════════╩═════════════╩══════════╩══════════╩═════════╝
梦里泪两行 2025-01-02 12:13:22

一般来说,关于 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值。

As a rule, there a two things you need to know about the SELECT clause:

  • Although it is written first, it is evaluated last, with the exception of the ORDER BY clause. This is why you cannot use any calculated fields or aliases in any other clause (particularly the WHERE clause) except in the ORDER BY clause.
  • Calculations in the SELECT clause are performed in parallel, or at least are handled as if they are. This is why you cannot use one calculation as part of another.

So, the short answer is that you can’t, and that is by design.

The notable exception to this is Microsoft Access, where you can indeed use calculations in subsequent columns and WHERE clauses. However, although that is convenient, it’s not actually an advantage: not following the above principals is less efficient. But it’s OK for light duty databases, which is what Access is supposed to be used for.

If you really want re-use calculated results, you will need a separate query, either in the form of a sub-query or as a Common Table Expression. CTEs are much easier to work with, as they are clearer to read.

Edit

Here is an example why using calculated columns could cause confusion. In Australia we measure height in centimetres, but there still some places which use the ancient inches (1 in = 2.54 cm).

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

Here the CASE still uses the original height value.

誰ツ都不明白 2025-01-02 12:13:22
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;
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;
秋千易 2025-01-02 12:13:22

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

You're trying to use column aliases in an expression. If a system allows you to do that it's just syntactic sugar. This should work in any SQL dialect.

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文