CTE(With语句)是否允许在PostgreSQL中消除常见的子表达式?

时间:2017-12-22 17:19:35

标签: postgresql common-table-expression

我正在编写一个生成大型SQL表达式和复杂查询的系统。 为了我自己的理智,我让代码生成器使用WITH表达式来简化代码并使其更具可读性(它仍然产生的恐怖的一个例子是:https://pastebin.com/UZJ01Q19

在某些地方,我想重复使用复杂子表达式的结果任意次数,我想知道绑定表达式的计算次数,例如

WITH ... AS <DoSetup>,
 intermediate AS <ComplexQuery>
SELECT a, b FROM 
    (SELECT * FROM intermediate WHERE ...)
    UNION
    (SELECT * FROM intermediate WHERE ...)

如果在此表达式中对ComplexQuery进行了两次求值,是否有办法以仅评估一次的方式重写表达式?我已经考虑过创建临时视图,但这似乎会在每次访问时重新评估子查询。

1 个答案:

答案 0 :(得分:2)

当您使用CTE时,我非常确定每次使用视图时它都不会重新执行子查询。它应该对查询进行一次评估并多次引用它。如果您运行解释计划,它将向您显示基表只被访问一次。

enter image description here

我不是这个主题的权威,我相信如果我读错了,有人会纠正我。

除此之外,如果上面的示例是相关的,您可以避免使用简单的OR子句对CTE进行联合。例如,如果它看起来像这样:

select * from intermediate where a = 1 and b < 50
union
select * from intermediate where a >= 0 and c > 99

您可以简单地将其重写为:

select *
from intermediate
where
  (a = 1 and b < 50) or
  (a >= 0 and c > 99)

同样,也许你的例子根本过于简单,但我确实看到了很多 - 工会会更好地作为or。请记住,union涉及一种排序,这在计算上很昂贵。

相关问题