PostgreSQL窗口函数在分区上存在bug?

6

我有一张表格t,其中包含以下数据:

    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的一个错误还是我错过了什么?

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)
1个回答

11
不,这不是一个错误。 first_value()last_value() 函数的作用对象是窗口帧而不是分区。根据文档,如果未指定frame_clause,窗口帧默认从分区开头到当前行。对于first_value(),这正是您所需要的,但对于last_value(),您应该在WINDOW定义中添加range between unbounded preceding and unbounded following以查看当前行之后的数据。
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;

请注意,这与分区中行的排序无关。排序以某种顺序生成分区(毫不奇怪),然后基于窗口帧的函数在不知道或关心任何行的排序的情况下处理窗口帧。

1
非常感谢。这是我在数据库中见过的最疯狂的api设计之一。如果我可以使用引用分区的 MAX 函数,然后将其替换为另一个函数,我希望它也能在分区上运行。这只是理智所期望的。当然,现在他们需要保留这种愚蠢的设计以确保向后兼容性,但我们是否可以有一些其他名称的函数来执行预期的操作呢? - Adamantish

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接