SQL查询第n高薪资语句中n-1=count子查询的逻辑解释
第N高薪资SQL执行逻辑说明
你看到的是典型的关联子查询写法,先放修正了括号闭合问题的完整SQL:
SELECT * FROM employee A WHERE n-1 = ( SELECT count(*) FROM employee B WHERE B.salary > A.salary )
核心执行规则
这个语句里的子查询不是独立执行一次的,它是和外层查询逐行关联计算的:外层每扫描到employee表(别名A)的一行记录,就会把这行的salary值传入内层子查询,单独计算一次符合条件的计数,再用这个计数和n-1做等值判断,判断成立才会把当前这行放进结果集。
n-1 = count(*)的判断原理
这个判断的逻辑本质非常好理解:
- 对任意一个薪资值来说,如果表里总共有
k条记录的薪资比它高,那这个薪资在全表降序排序里的排名就是k+1 - 我们要找第
n高的薪资,本质就是找满足k+1 = n的记录,移项之后就是k = n-1,也就是子查询统计出来的「比当前薪资高的记录总数」正好等于n-1
举个实际例子,假设你要找第2高的薪资(也就是n=2,此时n-1=1),表里的薪资数据为30000、25000、20000、18000,逐行判断的过程是:
- 当外层扫到薪资30000的记录:内层统计比30000高的记录数,结果为0,0不等于1,这行被过滤
- 当外层扫到薪资25000的记录:内层统计比25000高的记录数,只有30000这1条,结果为1,正好等于n-1=1,这行被保留进结果集
- 当外层扫到薪资20000的记录:内层统计比20000高的记录有30000、25000共2条,结果为2,不等于1,被过滤
- 当外层扫到薪资18000的记录:内层统计比18000高的记录共3条,结果为3,不等于1,被过滤
最终返回的就是薪资25000的记录,也就是预期的第2高薪资结果。
注意:这个写法默认表中薪资没有重复值,如果存在多条相同薪资的情况,查询结果会出现不符合预期的问题,需要根据业务是否允许并列排名调整统计逻辑。
内容的提问来源于stack exchange,提问作者Boba Evans
相关产品推荐
相关产品推荐

