以下查询可用于计算累计总和:
select
(select sum(c) over (ROWS UNBOUNDED PRECEDING) as a),
sum(c) over (ROWS UNBOUNDED PRECEDING ) as b
from (select unnest(ARRAY[1, 2, 3, 3, 4, 5]) as c) x
列b
给出了预期的结果,而a
没有。
| 一种|B|
| - -----|- -----|
| 1| 1|
| 2| 3|
| 3|六|
| 3|九个|
| 4|十三个|
| 5个|十八岁|
我在Google和Stackoverflow上搜索过,但没有找到类似的问题。
以下是我的问题:
- 为什么简单的
select
Package 器会导致完全不同的结果? - 是否可以将子查询保留在
SELECT
列表中,同时仍使窗口函数按预期工作?
1条答案
按热度按时间lc8prwob1#
为什么简单的
select
Package 器会导致完全不同的结果?输出列
a
是相关子查询的结果,该查询对底层派生表x
生成的每一行运行一次。这些计算中的每一个都只能看到计算它的单行。所以总和总是与单个值相同。另一方面,输出列
b
基于完整的派生表x
。所以你可以看到多行的实际总和。是否可以将子查询保留在
SELECT
列表中,同时仍使窗口函数按预期工作?**否。**除非您从相关子查询中的基础关系
x
重新联接到其他行。您必须在CTE中生成x
才能重用它(或使用实际的表),这将是一个奇怪的、昂贵的构造,而且很可能是无稽之谈。(使用情况是什么?)虽然没有在窗口框架中添加显式的
ORDER BY
,但b
也不完全可靠。简单的查询不会中断。但如果你做更多的事情(比如添加连接等),它可能会。参见:而
unnest()
本身也可以作为“表功能”。不需要额外的 Package 。考虑:注意,这是按照数组中的原始 * 位置 * 排序的。您的示例在这方面是不明确的,因为数组具有严格升序的值,这些值在按 value 排序时恰好排序相同。我想你关心的是“位置”。
旁白:窗口函数的默认框架选项是
RANGE UNBOUNDED PRECEDING
,所以(逻辑上)将其更改为ROWS UNBOUNDED PRECEDING
,而排序顺序具有对等值排序。如果窗口框架中没有ORDER BY
,则 all 行都是对等行。这在我的查询中并不重要(逻辑上),因为它是按“有序性”排序的--具有确定性的排序顺序,没有对等体。
但它仍然影响性能。
ROWS
更快,因为它不需要检查对等体。Postgres 16在这方面包括了实质性的性能改进。但是sum()
不受影响,因为RANGE
和ROWS
可以产生实际差异。当您知道排序顺序是明确的时,切换到ROWS
仍然是值得的,就像我的查询中一样。参见: