PostgreSQL中的窗口函数

PostgreSQL中提供了窗口函数,一个窗口函数在一系列与当前行有某种关联的表行上进行一种计算。
一个窗口函数调用总是包含一个直接跟在窗口函数名及其参数之后的OVER子句。OVER子句决定究竟查询中的哪些行被分离出来由窗口函数处理。对于每一行,窗口函数都会在当前行同一分区的行上进行计算。
另一个与窗口函数相关的重要概念是:对于每一行,在它的分区中的行集被称为窗口帧。 许多窗口函数只作用在窗口帧中的行上,而不是整个分区。默认情况下,如果使用ORDER BY,则帧包括从分区开始到当前行的所有行,以及任何根据ORDER BY子句和当前行相等的后续行。如果ORDER BY被忽略,则默认帧包含分区中的所有行。
举个例子,新建一个表wdtest,插入一些数据:
PostgreSQL中的窗口函数
如果我们忽略ORDER BY,结果如下:
PostgreSQL中的窗口函数
由于在OVER子句中没有ORDER BY,窗口帧就会和分区一样。换句话说,每个sum()都会在整个表上进行,这样每个输出行得到的结果相同。但是如果在OVER子句中加上一个ORDER BY子句,结果就会不同:
PostgreSQL中的窗口函数
这里的sum()是从第一个(最低的)值一直到当前行,包括任何与当前行相同的行。这里需要注意的是有相同值的行的结果。
在一个查询中可以包含多个窗口函数,每个窗口函数都可以用不同的OVER子句来按不同方式划分数据,但是它们都作用在由虚拟表定义的同一个行集上。
举例如下:
PostgreSQL中的窗口函数
这个例子中我们分别查看数据集中正序和倒序排列的第一个值。
然而,如果我们稍作改动,查看last_value,会产生令人意外的结果:
PostgreSQL中的窗口函数
从结果中可以看到,这两列都返回相同的数据,不管ORDER BY子句中的不同排列顺序要求。
我们可以通过array_agg函数来看last_value真正的返回值是怎么得出的。
PostgreSQL中的窗口函数
array_agg会简单的把它们都放到一个数组中。所以这两种情况下数组中的last value值是完全一致的,从而导致上述现象的发生。

By Kalath