咱們直接用例子來講明,這裏有一張學生考試成績表testScore
:html
如今有個需求,須要查詢的時候多出一列subject_avg_score
,爲此科目全部人的平均成績,好跟每一個人的成績作對比。sql
傳統方法確定是用聚合,可是寫起來很麻煩也很累贅,這時候窗口函數就排上了用場。segmentfault
由於窗口函數不會像聚合同樣將參與計算的行合併成一行輸出,而是將計算出來的結果帶回到了計算行上。函數
聚合:聚合函數(sum,min,avg……) + GROUP BYpost
窗口函數:聚合函數(sum,min,avg……) + OVER ( …… )code
還用上面的例子:htm
subject_avg_score
[這正是上面提到的需求]這裏的 OVER 裏用到了 PARTITION BY
blog
SELECT *, avg("score") OVER (PARTITION BY "subject") as "subject_avg_score" FROM "testScore"
subject_avg_score
這裏的 OVER 裏爲空文檔
SELECT *, avg("score") OVER () as "subject_avg_score" FROM "testScore"
subject_rank_score
這裏的 OVER 裏用到了 PARTITION BY
+ ORDER BY
get
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() 則單純是序號,因此不會出現多我的並列的狀況。
若是在 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")