PostgreSQL - 使用同一查询中先前计算的值

3

我有以下SQL查询:

SELECT (SELECT ...) AS X, (SELECT ...) AS Y from my_table

'X' 非常难计算,它被用作计算 Y 的输入。然而,如果我试图在计算 Y 的查询内部或甚至主查询内部引用 X,就会出现以下错误消息:

Error: column "X" does not exist

在计算X后是否有任何方法可以引用它?我真的不想重复计算它,因为这似乎非常低效。


1
你知道它实际上会被计算两次吗? - onedaywhen
3个回答

4

PostgreSQL通常很聪明,不需要计算两次相同的内容。因此,像这样的查询:

SELECT (SELECT hard_to_compute FROM whatever) AS X,
       (SELECT hard_to_compute FROM whatever)*2 AS Y 
FROM my_table

应该只需要运行两个子查询一次。但是如果查询像这样

SELECT (SELECT hard_to_compute FROM whatever) AS X,
       (SELECT hard_to_compute*2 FROM whatever) AS Y 
FROM my_table

那么,优化器可能更难看出这两个查询中相同的部分。

另一种处理方法是创建一个稳定函数来计算X。只要输入相同,在单个语句内,稳定函数总是返回相同的结果,因此Postgres知道它只需要运行一次。请参见http://www.postgresql.org/docs/9.0/interactive/xfunc-volatility.html


我的关注更多地集中在代码中重复大型复杂表达式,而不是查询计划的效率问题。有没有解决方案? - OrangeDog

3

您可以使用子查询来实现,例如:

select *, hard_to_compute * 2 as using_hard_to_compute \
from (select *, (i * i) as hard_to_compute from foo) bar;

 i | hard_to_compute | using_hard_to_compute 
---+-----------------+-----------------------
 1 |               1 |                     2
 2 |               4 |                     8
 3 |               9 |                    18

当然,i * i并不难计算。在这个例子中,我只是假装它很难。


0
你最好的选择可能是先运行查询中的 (SELECT ...) AS X 部分,将其结果存储在一个临时表中。然后在主查询中使用该临时表。

4
临时表慢且应该是最后的选择。很容易将其转换为使用子查询,这样就不必将所有内容都移动到临时区域中了。 - Greg Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接