PostgreSQL 高级SQL(五) 内建窗口函数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PostgreSQL 高级SQL(五) 内建窗口函数相关的知识,希望对你有一定的参考价值。

参考技术A         前面俩个章节我们介绍了窗口函数、滑动窗口函数的概念,接下来我们介绍一下PG支持的原生通用窗口函数,总共11个(9.6版本, 中国社区官网文档地址 )

1、row_number 函数

row_number函数可以给每隔数据行返回一个虚拟的自增ID,也就是相当于给行分配一个编号,这些编号不会出现重复,即使over()里面没有按照字段排序字段也能正常工作,

2、rank函数

rank的官方解释是:带间隙的当前行排名; 与该行的第一个同等行的row_number相同

从上面的的结果我们可以看出 rank函数和row_number一样可以将行编号,但是号码可能重复,比如我们按照年份排序,年份相同的话rank值相同,2017年的数据rank直接跳到了7,这就相当于上学的时候考试,用rank计算排名的话,如果同年级出现三个并列的第一名的话,那么计算的结果将是三个人的rank值都是第一,但是实际上的第二高的分数的同学会被rank排名为第四名,如果我们想第二高的分数的排名为2,我们可以使用dense_rank函数;

3、dense_rank函数

        从上面的结果我们可以看出dense_rank函数会把编号弄得更加紧密,中间不会出现像rank那样的断层编码。

4、percent_rank函数

        官方文档解释: 当前行的相对排名=(rank- 1) / (总行数 - 1) ,

         排名和rank值成正相关 ,rank值相同的行号 percent_rank获取的结果也一样,返回的 结果是个小数范围在[0,1]之间 ,可以等于0或者1

5、cume_dist函数

        官方文档解释: 当前行的相对排名=(rank- 1) / (总行数 - 1) ,

         排名和rank值成正相关 ,rank值相同的行号 percent_rank获取的结果也一样,返回的 结果是个小数范围在[0,1]之间 ,可以等于0或者1

6、ntile函数

官方文档解释:从1到参数值的整数范围,尽可能等分分区,

        ntile(num_buckets),num_buckets的值表示将结果集分成num_buckets组,有限填满前面的组,最后一组可能出现个数不足(非等分)情况,实际上就是把每隔行分个组号。

7、lag函数

        官方文档解释:lag( value  anyelement [,  offset  integer [,  default  anyelement ]]),返回 value , 它在分区内当前行的之前 offset 个位置的行上计算;如果没有这样的行,返回 default 替代。 (作为 value 必须是相同类型)。  offset 和 default 都是根据当前行计算的结果。如果忽略它们,则 offset 默认是1, default 默认是空值

        官方文档的解释很晦涩难懂,我们直接使用用例执行一下看一下数据分布就好了

从上图可以知道当前行的lag值是当前行的前offset行的值,没有的话就返回default,default不想存在的话就返回null,从数据姐过再去看官方文档的解释的话可能清晰很多,lag函数可以在结果集的行内移动,经常使用到的场景是计算今年和全年的年产量的差值,

8、lead函数

官方文档解释:lead( value  anyelement [,  offset  integer [,  default  anyelement ]]) 返回 value ,它在分区内当前行的之后 offset 个位置的行上计算;如果没有这样的行,返回 default 替代。(作为 value 必须是相同类型)。 offset 和 default 都是根据当前行计算的结果。如果忽略它们,则 offset 默认是1, default 默认是空值

    其实lead函数和lag函数的作用是相同的,如果lead的offset参数值为-N,那么lag的offset的参数为N的话计算结果是相同的,lag(gdp,-1)是lead(gdp,1)的替代

9、first_value、last_value、nth_value函数较为简单不做介绍

        至此我们讲完了几乎所有的窗口函数,希望这五篇关于PostgreSQL的文章能对大家在平时的开发中有所帮助

SQL窗口函数计数前10查询postgresql redshift

【中文标题】SQL窗口函数计数前10查询postgresql redshift【英文标题】:SQL window function count top 10 query postgresql redshift 【发布时间】:2016-05-29 10:40:57 【问题描述】:

我使用的是 SQL,amazon redshift,但它与我听说的 PostGres 非常相似。

我有一个数据库,其中包含一个包含很多问题和答案的表格。每次有人陈述答案时,问题和答案都会重复。我想要一个查询,它列出了独特的问题以及这些问题的答案计数。但是,我只想显示最常回答的前 10 个答案。

所以我做了以下事情。我使用了一个窗口函数来显示按问题划分的答案计数。我对 COUNT(answer) 降序排序。但是,有些问题可以给出很多很多不同的答案,因此查询将列出数百行,其中包含该问题的所有答案。所以我让我的窗口成为一个子查询。我做了 SELECT * FROM 子查询,然后在子查询之外的 WHERE 子句中指定窗口/分区应小于或等于 10,以显示前十个答案)。这行得通。

我现在想显示为每个问题提供的每个答案的百分比。我可以使用 percent_rank 或 cume_dist 窗口函数来做到这一点。两者都具有相似的预期效果。

但是,我还想添加一个显示累积百分比的列。它应该显示给出答案的次数与该问题的答案总数的百分比。当您对该问题的 10 行进行向下分析时,该百分比应逐渐增加,以便在第 10 行以 1.00 或 100% 结束。

问题如下:如果一个问题只有 10 个或更少的潜在答案,那么它可以完美运行。但是,如果一个问题的答案超过 10 个,precent_rank 或 cume_dist 会根据总答案的数量计算出每个答案的百分比。我可以看到这并没有错,但我只想显示上面提到的前 10 个答案以及仅基于前 10 个的百分比!

任何关于如何让查询忘记其他 100 个答案并只查看我展示的前 10 个答案的建议将不胜感激。

非常感谢 my query

SELECT * FROM (SELECT question, answer, COUNT(answer), row_number() OVER (PARTITION BY question ORDER BY count ASC) AS ranker ,question as had_to_insert_an_alias, COUNT(answer), cume_dist() OVER (PARTITION BY had_to_insert_an_alias ORDER BY count DESC) AS percent_ranker FROM question_table WHERE date_field >= '2013-10-01' and date_field < '2013-10-30' group by question, answer) AS subquery WHERE ranker <= 10 order by question;

【问题讨论】:

它最初是 PostGreSQL 8.0.2 的一个分支,但在底层进行了大量修改。此外,您的问题非常冗长且冗长。请包含一些示例数据(或指向 SQLFiddle 的链接)、您想要的结果以及您尝试过的代码。如果一张图片值一千字,那么实际代码至少值几百字​​。 如果您提供现有查询和表定义示例,则更容易给您一个好的答案。 嗨,我附上了一张显示我的查询的屏幕截图。在我写下“非常感谢”之后,这是我上面的大问题末尾的链接 感谢所有帮助 @187213 - 请不要发布屏幕截图的链接。我不愿意从只有 1 个代表的人那里点击潜在的点击诱饵。请将代码复制并粘贴到您的问题中。编辑器中有一些按钮可帮助将部分标记为特定格式的代码。如果我们需要复制粘贴您的代码以进行测试或我们的答案,这也很有帮助。 【参考方案1】:

这样的?

select question, answer, count, rank, (count::decimal/total::decimal)*100.0 as percent
from (
    select question, answer, count, rank,
        sum(count) over (partition by question order by count) as total
    from (
        select question, answer, count(*) as count,
            rank() over (partition by question order by count desc) as rank
        from question_table
        where  date_field >= '2013-10-01' and date_field < '2013-10-30'
        group by question, answer
    ) q
    where rank <= 10
) t
order by question, rank

这是未经测试的,所以语法可能是关闭的。

【讨论】:

以上是关于PostgreSQL 高级SQL(五) 内建窗口函数的主要内容,如果未能解决你的问题,请参考以下文章

PostGIS总结

PostgreSQL之SQL函数介绍及实践

postgresql如何执行sql文件

SQL窗口函数计数前10查询postgresql redshift

带窗口函数的高级 SQL

datawhale9月组队学习task05SQL高级操作