导读:本期聚焦于小伙伴创作的《SQL如何对分组聚合后的结果进行排名?利用窗口函数实现分组排名的方法》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《SQL如何对分组聚合后的结果进行排名?利用窗口函数实现分组排名的方法》有用,将其分享出去将是对创作者最好的鼓励。

在SQL的实际业务查询中,我们经常会遇到先对数据做分组聚合计算,再对聚合后的结果集进行排名的需求,比如统计每个部门的销售总额后,给部门按销售额从高到低排名。传统实现方式需要先通过子查询得到聚合结果,再在外层查询中做排序赋值,逻辑复杂且容易出错,而窗口函数可以非常优雅地解决这个问题。

SQL如何对分组聚合后的结果进行排名?利用窗口函数实现分组排名的方法

一、窗口函数基础概念

窗口函数是SQL中一类特殊的函数,它会对查询结果集的一个子集(也就是窗口)进行计算,且不会改变结果集的行数。和普通的聚合函数不同,窗口函数不需要用GROUP BY做分组,而是可以在保留所有原始行的基础上完成计算。

常用的排名类窗口函数有三个,它们的语法结构一致,只是排名规则有区别:

  • ROW_NUMBER():按指定顺序给每一行分配唯一的连续序号,相同值的行也会获得不同的序号
  • RANK():按指定顺序排名,相同值的行获得相同序号,下一个序号会跳过重复的数量
  • DENSE_RANK():按指定顺序排名,相同值的行获得相同序号,下一个序号连续不跳过

二、分组聚合后使用窗口函数的语法

如果需要对分组聚合后的结果做排名,正确的做法是先完成分组聚合,再将聚合结果作为窗口函数的输入,结合PARTITION BYORDER BY子句实现分组内的排名。

核心语法结构如下:

-- 先分组聚合,再用窗口函数排名
SELECT 
    分组字段,
    聚合结果字段,
    排名函数() OVER (PARTITION BY 分组字段 ORDER BY 聚合结果字段 DESC/ASC) AS 排名列
FROM (
    -- 子查询:先完成分组聚合
    SELECT 
        分组字段,
        SUM(数值字段) AS 聚合结果字段  -- 这里可以是SUM、COUNT、AVG等聚合函数
    FROM 数据表
    GROUP BY 分组字段
) AS 聚合结果表

其中PARTITION BY用来指定分组的维度,也就是按照哪个字段划分不同的排名组,ORDER BY用来指定排名的排序规则,决定序号的分配顺序。

三、实际场景示例

假设我们有一张销售记录表sales_record,表结构如下:

字段名类型说明
departmentVARCHAR部门名称
employee_idINT员工ID
sale_amountDECIMAL销售金额
sale_dateDATE销售日期

现在的需求是:统计2024年每个部门的总销售额,然后给所有部门按总销售额从高到低做排名,总销售额相同的部门排名相同,且后续排名不跳过序号。

对应的SQL实现代码如下:

-- 统计部门总销售额并排名
SELECT 
    department,
    total_sale,
    -- 使用DENSE_RANK按总销售额降序排名
    DENSE_RANK() OVER (ORDER BY total_sale DESC) AS dept_sale_rank
FROM (
    -- 子查询:分组聚合计算每个部门的总销售额
    SELECT 
        department,
        SUM(sale_amount) AS total_sale
    FROM sales_record
    WHERE sale_date >= '2024-01-01' AND sale_date <= '2024-12-31'
    GROUP BY department
) AS dept_sale_summary
ORDER BY total_sale DESC

如果我们需要的是每个部门内部,给部门员工的销售额做排名,那么只需要在窗口函数中加上PARTITION BY department即可,示例代码如下:

-- 每个部门内给员工销售额排名
SELECT 
    department,
    employee_id,
    total_employee_sale,
    -- 按部门分区,部门内按员工销售额降序排名
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY total_employee_sale DESC) AS emp_sale_rank
FROM (
    -- 子查询:聚合每个员工的销售额
    SELECT 
        department,
        employee_id,
        SUM(sale_amount) AS total_employee_sale
    FROM sales_record
    GROUP BY department, employee_id
) AS emp_sale_summary
ORDER BY department, total_employee_sale DESC

四、注意事项

1. 窗口函数的执行顺序在WHEREGROUP BYHAVING之后,所以在窗口函数中可以直接使用聚合后的字段,不需要额外处理。

2. 如果排名的排序字段有NULL值,需要注意数据库的NULL值排序规则,大部分数据库默认NULL值排在最前面,如果需要调整可以加NULLS LAST或者NULLS FIRST子句,比如ORDER BY total_sale DESC NULLS LAST

3. 不同的数据库对窗口函数的支持版本不同,MySQL需要8.0及以上版本,SQL Server需要2012及以上版本,Oracle和PostgreSQL较新版本都支持,使用前需要确认数据库版本。

窗口函数大大简化了分组后排名的SQL逻辑,避免了多层子查询的嵌套,不仅代码更易读,执行效率也往往优于传统的自连接排名方式,是SQL查询中非常实用的功能。

SQL窗口函数分组聚合排名ROW_NUMBER修改时间:2026-07-15 03:21:26

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。