当前位置: 代码网 > it编程>数据库>MsSqlserver > PostgreSQL中rank()窗口函数实用指南与示例

PostgreSQL中rank()窗口函数实用指南与示例

2025年07月11日 MsSqlserver 我要评论
一、rank()函数简介rank()是一个窗口函数,用于计算结果集中每一行的排名。它的基本语法如下:rank() over ([partition by partition_expression] o

一、rank()函数简介

rank()是一个窗口函数,用于计算结果集中每一行的排名。它的基本语法如下:

rank() over ([partition by partition_expression] order by order_expression)
  • partition by:可选子句,用于将结果集划分为多个分区,排名在每个分区内独立计算。
  • order by:指定排名的顺序依据。

特点

  • 相同值的行会获得相同的排名。
  • 下一个排名会跳过相同值的数量。例如,如果有两个第一名,下一个排名是第三名。

二、基础示例:部门内员工薪资排名

假设有一个employees表,包含员工姓名、部门和薪资信息。我们希望计算每个部门内员工的薪资排名。

示例数据

首先,创建示例数据:

with sample_data as (
    select * from (
        values 
            ('alice', 'sales', 50000),
            ('bob', 'marketing', 55000),
            ('charlie', 'sales', 52000),
            ('david', 'it', 60000),
            ('eve', 'marketing', 55000),
            ('frank', 'it', 62000)
    ) as t(employee_name, department, salary)
)

排名查询

使用rank()函数按部门分区,按薪资降序排名:

select 
    employee_name, 
    department, 
    salary, 
    rank() over (partition by department order by salary desc) as dept_salary_rank
from 
    sample_data
order by 
    department, dept_salary_rank;

结果

employee_namedepartmentsalarydept_salary_rank
frankit620001
davidit600002
bobmarketing550001
evemarketing550001
charliesales520001
alicesales500002

解释

  • 在it部门,frank薪资最高,排名为1;david次之,排名为2。
  • 在marketing部门,bob和eve薪资相同,均排名为1。
  • 在sales部门,charlie薪资最高,排名为1;alice次之,排名为2。

三、高级应用示例

1. 每组top n记录

场景:找出每个类别中最贵的两个产品。

示例数据

with products as (
    select * from (
        values 
            (1, 'a', 100),
            (2, 'a', 80),
            (3, 'b', 200),
            (4, 'b', 180),
            (5, 'b', 150),
            (6, 'c', 120)
    ) as t(product_id, category, price)
)

查询

select * 
from (
    select 
        product_id, 
        category, 
        price, 
        rank() over (partition by category order by price desc) as rank
    from 
        products
) ranked
where rank <= 2;

结果

product_idcategorypricerank
1a1001
2a802
3b2001
4b1802
6c1201

解释

  • 每个类别中,价格最高的前两个产品被筛选出来。

2. 百分位数计算

场景:计算每个学生的成绩百分位。

示例数据

with scores as (
    select * from (
        values 
            ('student 1', 85),
            ('student 2', 92),
            ('student 3', 78),
            ('student 4', 90),
            ('student 5', 88)
    ) as t(student, score)
)

查询

select 
    student, 
    score, 
    rank() over (order by score) as rank,
    round(100.0 * rank() over (order by score) / (select count(*) from scores), 2) as percentile
from 
    scores;

结果

studentscorerankpercentile
student 378120.00
student 185240.00
student 588360.00
student 490480.00
student 2925100.00

解释

  • 百分位数通过排名除以总记录数并乘以100计算得出。

四、rank()与其他窗口函数的比较

postgresql提供了多个窗口函数用于排名,各有特点:

函数描述
rank()相同值的行获得相同排名,下一个排名跳过相同值的数量。
dense_rank()相同值的行获得相同排名,下一个排名不跳过,保持连续。
row_number()每行分配唯一的序号,不考虑相同值,即使值相同也会分配不同序号。

示例:rank() vs dense_rank()

示例数据

with scores as (
    select * from (
        values 
            ('player 1', 100),
            ('player 2', 95),
            ('player 3', 95),
            ('player 4', 90)
    ) as t(player, score)
)

查询

select 
    player, 
    score, 
    rank() over (order by score desc) as rank,
    dense_rank() over (order by score desc) as dense_rank
from 
    scores;

结果

playerscorerankdense_rank
player 110011
player 29522
player 39522
player 49043

解释

  • rank()在遇到相同分数时跳过了排名3。
  • dense_rank()在遇到相同分数时不跳过排名,保持连续。

示例:row_number()

场景:为每日的销售记录分配唯一序号,按销售金额降序排列。

示例数据

with sales as (
    select 
        date '2023-01-01' as sale_date, 
        1000 as amount
    union all
    select 
        date '2023-01-01', 
        1500
    union all
    select 
        date '2023-01-02', 
        1200
    union all
    select 
        date '2023-01-02', 
        1200
)

查询

select 
    sale_date, 
    amount, 
    row_number() over (partition by sale_date order by amount desc) as row_num
from 
    sales;

结果

sale_dateamountrow_num
2023-01-0115001
2023-01-0110002
2023-01-0212001
2023-01-0212002

解释

  • 即使同一天有相同的销售金额,row_number()也会为每条记录分配唯一的序号。

五、性能优化建议

使用窗口函数如rank()时,可能会对查询性能产生影响,尤其是在处理大数据集时。以下是一些优化建议:

  1. 使用partition by合理分区:将数据划分为较小的分区,可以减少每个窗口函数计算的数据量。
  2. 指定order by明确排序:确保order by子句明确,避免全表排序带来的性能开销。
  3. 创建适当的索引:在order bypartition by涉及的列上创建索引,可以加快排序和分区操作。
  4. 限制结果集:如果只需要前n条记录,结合where rank <= n可以减少计算量。

六、总结

postgresql的rank()窗口函数是一个强大的工具,适用于各种排名需求,如部门内薪资排名、每组top n记录、百分位数计算等。通过合理使用rank()及其相关函数(如dense_rank()row_number()),可以高效地处理复杂的数据分析任务。

关键点回顾

  • rank()函数为相同值的行分配相同的排名,并跳过后续排名。
  • 结合partition byorder by,可以实现多层次的排名需求。
  • 与其他窗口函数(如dense_rank()row_number())相比,rank()在处理并列排名时有独特的行为。
  • 通过优化查询和索引,可以提升窗口函数的性能表现。

希望本文的示例和解释能帮助你在实际项目中更好地应用rank()函数,提升数据处理的效率和准确性!

到此这篇关于postgresql中rank()窗口函数实用指南与示例的文章就介绍到这了,更多相关postgresql rank()窗口函数内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com