咱们直接用例子来讲明,这里有一张学生考试成绩表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")