详情

首页手游攻略 PostgreSQL中rank()窗口函数实用指南与示例实用指南

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

佚名 2026-09-14 15:40:02

平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“PostgreSQL中rank()窗口函数实用指南与示例”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。

目录
  • 一、rank()函数简介
  • 二、基础示例:部门内员工薪资排名
    • 示例数据
    • 排名查询
  • 三、高级应用示例
    • 1. 每组Top N记录
    • 2. 百分位数计算
  • 四、rank()与其他窗口函数的比较
    • 示例:rank() vs dense_rank()
    • 示例:row_number()
  • 五、性能优化建议
    • 六、总结

      一、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()窗口函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多兼容脚本之家!

      您可能感兴趣的文章:

      • postgresql rank() over, dense_rank(), row_number()用法区别
      • PostgreSQL数据库中窗口函数的语法与采用
      • PostgreSQL常用字符串函数与示例说明小结
      • postgresql常用日期函数采用整理

      相关资讯
      点击查看更多
      游戏推荐
      推荐专题
      热门阅读
      推荐下载