讲师中心 微信公众号
AI工具推荐 视频效率加速

SQL如何获取分组中第二名的数值_窗口函数配合子查询

云磊酱_1073

云磊酱_1073

发布时间:2026-03-28 14:47:01

|

342人浏览过

|

来源于php中文网

原创

用ROW_NUMBER()先分组排序再筛选rn=2是最稳的取“第二名”方式,需嵌套子查询或CTE,不可在WHERE/HAVING中直接使用;ORDER BY必须明确写在OVER()中;并列时ROW_NUMBER()强制拆序,DENSE_RANK()适合分数档位;OFFSET/LIMIT不能直接用于分组。

sql如何获取分组中第二名的数值_窗口函数配合子查询

用 ROW_NUMBER() 给分组内排序再筛选

直接在分组内标序号,是最稳的取“第二名”方式。核心是:先用窗口函数编号,再在外层查出 rn = 2 的行。

常见错误是把 ROW_NUMBER() 放在 WHERE 或 HAVING 里——窗口函数不能在这些子句中直接使用,必须嵌套一层子查询或 CTE。

  • ORDER BY 必须明确写在 OVER() 里,否则序号无意义;降序取最高分第二名就用 ORDER BY score DESC
  • 如果存在并列(比如两个 95 分并列第一),ROW_NUMBER() 会强制拆成 1 和 2,而 RANK() 会都给 1,下一个是 3 —— 取“真正第二顺位”选 ROW_NUMBER(),取“分数上第二档”才考虑 RANK()
  • MySQL 8.0+、PostgreSQL、SQL Server、Oracle 都支持;SQLite 3.25+ 也行,但旧版不支持窗口函数
SELECT dept, score
FROM (
  SELECT dept, score,
         ROW_NUMBER() OVER (PARTITION BY dept ORDER BY score DESC) AS rn
  FROM employees
) t
WHERE rn = 2;

遇到重复值还想取“分数第二高”的人怎么办

当多个员工分数相同,你其实想拿“去重后第二高的那个分数”,而不是任意一个排第二的记录——这时候不能只靠 ROW_NUMBER()。

本质是先对分数去重,再排序取第二。典型做法是用 DENSE_RANK() 配合 DISTINCT 子查询,或者用 OFFSET + LIMIT(PostgreSQL/MySQL)。

  • DENSE_RANK() 不跳号,适合“分数档位”场景;ROW_NUMBER() 是纯位置编号,两者语义不同
  • 如果只要每个分组的“第二高分”数值(不关心是谁),可先 SELECT DISTINCT dept, score 再开窗,避免同分多人干扰排序逻辑
  • 注意 NULL 值:默认 ORDER BY ... DESC 会把 NULL 排最前,加 NULLS LAST(PostgreSQL)或用 COALESCE(score, -999) 规避
SELECT dept, score
FROM (
  SELECT DISTINCT dept, score,
         DENSE_RANK() OVER (PARTITION BY dept ORDER BY score DESC) AS dr
  FROM employees
) t
WHERE dr = 2;

OFFSET 1 LIMIT 1 能不能直接用在分组里

不能。SQL 标准里 OFFSET/LIMIT 是作用于最终结果集的,不是按分组独立生效的。想“每组取第二条”,必须配合窗口函数或相关子查询。

有人试图用关联子查询模拟,比如对每个 dept 执行一次 SELECT ... ORDER BY score DESC OFFSET 1 LIMIT 1,但性能极差,尤其数据量大时会触发 N+1 查询。

  • MySQL 8.0+ 支持 LATERAL(类似 JOIN LATERAL),可安全实现“为每组执行一次子查询”,但写法比窗口函数啰嗦
  • PostgreSQL 中可用 SELECT DISTINCT ON (dept) ... ORDER BY dept, score DESC OFFSET 1?不行——DISTINCT ON 不支持跨组 offset
  • 别为了省一层子查询去硬套 OFFSET,窗口函数在这里就是最直白、最可控的解法

为什么 MAX() 套子查询取第二大会出错

比如写 SELECT MAX(score) FROM employees WHERE score ,这只能拿到全局第二高分,完全没做分组。

想分组做,就得把子查询写成相关子查询,但容易漏掉 GROUP BY 或写错关联条件,导致结果错乱或性能爆炸。

  • 错误示范:WHERE score —— 这确实能分组,但若最大分有重复,它会跳过所有最大分,直接取第三、第四……无法保证是“第二”
  • 更糟的是,这种写法在 MySQL 5.7 或低版本可能因 SQL mode 限制报错,或返回非预期的单行结果
  • 窗口函数从语义到执行计划都更清晰:排序、编号、过滤,三步对应三层逻辑,调试和优化都有迹可循
实际写的时候,最容易被忽略的是 PARTITION BY 和 ORDER BY 的字段组合是否真符合业务分组意图——比如按部门分组但忘了处理部门为空的记录,或者排序字段含 NULL 导致第二名漂移。窗口函数本身不难,难的是确认“第二名”在你业务里到底指什么。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

4103

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

871

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

1069

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

5981

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2863

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

5960

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

7941

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

1090

2024.04.29

C++运算符基础入门
C++运算符基础入门

本专题详细讲解了C++运算符的类型、语法与使用方法,涵盖算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符、条件运算符及其他特殊运算符,并通过代码示例解析优先级与结合性。

0

2026.10.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn