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窗口函数(二)

相关文章
相关标签/搜索