PostgreSQL 窗口函數 ( Window Functions ) 如何使用?

1、爲何要有窗口函數


咱們直接用例子來講明,這裏有一張學生考試成績表testScorehtml

如今有個需求,須要查詢的時候多出一列subject_avg_score,爲此科目全部人的平均成績,好跟每一個人的成績作對比。sql

傳統方法確定是用聚合,可是寫起來很麻煩也很累贅,這時候窗口函數就排上了用場。segmentfault

由於窗口函數不會像聚合同樣將參與計算的行合併成一行輸出,而是將計算出來的結果帶回到了計算行上。函數

2、窗口函數的使用


一、聚合和窗口函數的區別

聚合:聚合函數(sum,min,avg……) + GROUP BYpost

窗口函數:聚合函數(sum,min,avg……) + OVER ( …… )code

二、使用

還用上面的例子:htm

(1) 取每一個不一樣科目的平均值subject_avg_score [這正是上面提到的需求]

這裏的 OVER 裏用到了 PARTITION BYblog

SELECT *, 
       avg("score") OVER (PARTITION BY "subject") as "subject_avg_score"
FROM "testScore"

(2) 取全部成績的平均值subject_avg_score

這裏的 OVER 裏爲空文檔

SELECT *, 
       avg("score") OVER () as "subject_avg_score"
FROM "testScore"

(3) 取此人該科目成績班上排第幾名subject_rank_score

這裏的 OVER 裏用到了 PARTITION BY + ORDER BYget

ORDER BY 只能用在一些特殊的聚合函數裏,好比這裏的 rank()

SELECT *, 
        avg("score") OVER (PARTITION BY "subject") as "subject_avg_score",
                rank() OVER (PARTITION BY "subject" ORDER BY "score" DESC) as "subject_rank_score" 
FROM "testScore"

拓展知識:rank()、dense_rank()、row_number() 區別

rank() 最適合用來作排名的功能,它是若兩人並列第一,那第三我的就排名第三

dense_rank() 跟 rank() 的區別是,若兩人並列第一,那第三我的緊隨其後排名第二

row_number() 則單純是序號,因此不會出現多我的並列的狀況。

(4) 提取 OVER 變量

若是在 sql 裏寫了不少重複的 OVER(),能夠提取成一個 window 變量,簡化代碼。

SELECT *, 
        avg("score") OVER window_frame as "subject_avg_score",
        avg("score") OVER window_frame as "subject_avg_score_2",
        avg("score") OVER window_frame as "subject_avg_score_3"
FROM "testScore"  
window window_frame as (PARTITION BY "subject")


參考資料

官方文檔:http://www.postgres.cn/docs/9.3/tutorial-window.html

Postgresql窗口函數(一)

Postgresql窗口函數(二)

相關文章
相關標籤/搜索