Postgres 窗口函数语法

Posted

技术标签:

【中文标题】Postgres 窗口函数语法【英文标题】:Postgres Window Function Syntax 【发布时间】:2013-02-23 01:10:06 【问题描述】:

为什么会出现以下查询:

select ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY time DESC) as rownum FROM users where rownum < 20;

产生以下错误?

ERROR: column "rownum" does not exist LINE 1: ...d ORDER BY time DESC) as rownum FROM users where rownum < 2...

如何构造这个查询,以便获得前 20 个项目,由我的窗口函数定义?

user_idtime 都是在 users 上定义的列。

【问题讨论】:

显然,我并不想只获取users 的前 20 行。我已简化查询以更清楚地说明语法错误 【参考方案1】:

它会像这样工作:

SELECT *
FROM  (
   SELECT ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY time DESC) AS rownum
   FROM   users
   ) x
WHERE  rownum < 20;

这里的重点是事件的顺序。窗口函数在WHERE 子句之后应用。因此rownum 尚不可见。您必须将其放入子查询或 CTE 中,并在下一个查询级别对 rownum 应用 WHERE 子句。

Per documentation:

仅在SELECT 列表和ORDER BY 中允许使用窗口函数 查询的子句。它们在其他地方被禁止,例如GROUP BYHAVINGWHERE 子句。这是因为它们在逻辑上执行 在处理这些条款之后。此外,窗口函数执行 在常规聚合函数之后。这意味着包含 窗口函数的参数中的聚合函数调用,但是 反之亦然。

【讨论】:

Here可以看到过滤了WHERE谓词后处理了Window Functions。【参考方案2】:

因为where 子句在选择之前执行,所以它还不知道该别名。这样做:

select *
from (
    select ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY time DESC) as rownum 
    FROM users 
) s
where rownum < 20;

【讨论】:

以上是关于Postgres 窗口函数语法的主要内容,如果未能解决你的问题,请参考以下文章

Postgres数据库之兼容dm数据库TOP语法学习汇总

如何在带有 Postgres 的动态框架中使用窗口函数中的列值?

使用具有不同 order by 子句的 postgres 窗口函数

具有等级的postgres窗口函数

自定义窗口函数忽略 Postgres 中的空值

postgres —— 窗口函数入门