分区窗口函数中的 PostgreSQL 错误?
Posted
技术标签:
【中文标题】分区窗口函数中的 PostgreSQL 错误?【英文标题】:PostgreSQL bug in window function on partition? 【发布时间】:2015-05-07 04:08:32 【问题描述】:我有一个表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】:不,这不是错误。 first_value()
和 last_value()
函数适用于窗口框架,而不是分区。如果没有指定frame_clause
,则窗口框架,根据documentation,默认为当前行的分区开始。这正是您对first_value()
所需要的,但对于last_value()
,您应该将range between unbounded preceding and unbounded following
添加到您的WINDOW
定义中以超越当前行:
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;
还要注意,这与分区中行的顺序无关。排序以特定顺序生成分区(毫不奇怪),然后基于框架的函数在窗口框架上工作,而不知道或关心行的任何排序。
【讨论】:
非常感谢。这是我在数据库中见过的最疯狂的 api 设计之一。如果我可以使用引用分区的MAX
函数,然后用另一个函数替换,我希望它也可以在分区上工作。这只是理智。当然,他们现在需要保持这种愚蠢以实现向后兼容性,但是我们可以有一些替代命名的函数来达到预期的效果吗?以上是关于分区窗口函数中的 PostgreSQL 错误?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Postgresql 窗口函数的 PARTITION BY 中包含当前行