2015-05-07 26 views
4

我有一个表t具有下列数据:分区中的窗口函数中的PostgreSQL错误?

name | n 
------------+--- 
school  | 4 
hotel  | 2 
restaurant | 6 
school  | 3 
school  | 5 
hotel  | 1 

当我运行下面的查询,结果是有些奇怪。

select name, n, 
     first_value(n) over (partition by name order by n desc), 
     last_value(n) over (partition by name order by n) 
from t; 

    name | n | first_value | last_value 
------------+---+-------------+------------ 
hotel  | 1 |   2 |   1 
hotel  | 2 |   2 |   2 
restaurant | 6 |   6 |   6 
school  | 3 |   5 |   3 
school  | 4 |   5 |   4 
school  | 5 |   5 |   5 
(6 rows) 

虽然first_value作品如我所料,last_value工程奇怪。我认为last_value列的值应该与first_value的值相同,因为first_value是按n降序排列的。

这是PostgreSQL的bug还是我错过了什么?

的PostgreSQL的版本是:

postgres=# select version(); 
                   version 
----------------------------------------------------------------------------------------------------------------------------------- 
PostgreSQL 9.4.1 on x86_64-apple-darwin14.1.0, compiled by Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn), 64-bit 
(1 row) 

回答

9

不,这是不是一个错误。 first_value()last_value()函数在窗口框架上工作,而不是分区。如果没有指定frame_clause,根据documentation,窗口框架默认为分区开始到当前行。这正是您需要什么first_value()last_value()你应该添加range between unbounded preceding and unbounded followingWINDOW定义看当前行超越:也

select name, n, 
     first_value(n) over (partition by name order by n desc), 
     last_value(n) over (partition by name order by n 
     range between unbounded preceding and unbounded following) 
from t; 

注意,这已经无关的分区中的行进行排序。该排序以某种顺序生成分区(并不令人意外),然后基于框架的功能在窗口框架上工作,而不需要知道或关心任何行的排序。

+0

非常感谢。这是我在数据库中见过的最疯狂的api设计之一。如果我可以使用引用分区的'MAX'函数,然后用另一个函数替换,我希望它也可以在分区上工作。这只是理智。 当然,为了向后兼容,他们现在需要保持这种愚蠢的态度,但是我们可以有一些预期的交替命名函数吗? – Adamantish