7

我想从表 A 中选择一堆行,以及 avg(A.price) 和 avg(A.distance) 等聚合函数的结果。

现在,SELECT 查询需要一些时间,所以我不想运行一个查询来获取行,而另一个查询来获取平均值。如果我这样做了,我将运行查询以选择适当的行两次。

但是查看PostgreSQL窗口函数文档(http://www.postgresql.org/docs/9.1/static/tutorial-window.html),似乎使用窗口函数返回我想要使用的聚合函数的结果在返回的行旁边意味着返回的每一行都将包含聚合函数的结果。在我的例子中,由于聚合是针对主 SELECT 查询返回的所有行而不是其行的子集,这似乎很浪费。

考虑到我选择了 A 中行的一个子集但对整个子集进行聚合查询,多次返回相同的 avg() 对性能有何影响?特别是,Postgres 每次都重新计算平均值,还是以某种方式缓存平均值?

打个比方:如果您查看窗口函数文档并假设depnameSELECT 查询返回的每一行都是“开发”的,并且每一行的平均值都是相同的,因为平均值是在所有返回的行中计算的。该平均值计算了多少次?

4

2 回答 2

4

根据文档的第 7.2.4 节:

当使用多个窗口函数时,所有在其窗口定义中具有语法等效的 PARTITION BY 和 ORDER BY 子句的窗口函数都保证在一次数据传递中被评估。

于 2015-05-04T17:19:22.433 回答
3

您可以使用 CTE 做您想做的事。根据 Postgres文档

WITH 查询的一个有用属性是每次执行父查询时它们只被评估一次,即使它们被父查询或同级 WITH 查询多次引用。因此,可以将在多个地方需要的昂贵计算放在 WITH 查询中以避免冗余工作。另一个可能的应用是防止对具有副作用的函数进行不必要的多次评估。然而,这枚硬币的另一面是,与普通子查询相比,优化器不太能够将父查询的限制推送到 WITH 查询中。WITH 查询通常会按规定进行评估,而不会抑制父查询之后可能丢弃的行。(但是,如上所述,

您可以使用以下结构构建最终结果:

with cte as (your basic select goes here)
select *
from cte cross join
     (select averages here
      from cte
     ) const
where < your row filter here>
于 2013-05-02T16:59:28.470 回答