2013-02-23 55 views
1

爲什麼下面的查詢:Postgres的窗函數語法

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上定義的列。

+0

很顯然,我不是試圖只抓取'用戶'的前20行。我簡化了查詢,以更清楚地說明語法錯誤 – Matm 2013-02-23 01:11:36

回答

5

它的工作是這樣的:

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 BY, HAVINGWHERE條款。這是因爲它們在處理這些子句後邏輯上執行 。此外,窗口函數在定期聚合函數之後執行 。這意味着在窗口函數的參數中包含 聚合函數調用是有效的,但 反之亦然。

+0

[Here](http://wwwlgis.informatik.uni-kl.de/cms/fileadmin/courses/SS2014/Neuere_Entwicklungen/Chapter_6_-_Windows_and_Query_Functions_in_SQL.pdf#page= 19)可以看到在過濾WHERE謂詞後處理窗口函數。 – yoooshi 2015-06-24 06:29:14

0

由於where子句在select之前執行,所以它不知道該別名。這樣做:

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