订阅更新

第 N 高的薪水:把排名写进函数里

SQL 实战 123 题 · 第 3 题 中等 约 2 分钟读完

LeetCode 177 · 自定义函数、窗口排名、参数化查询

本文目录
  1. 面试怎么回答
  2. 题意
  3. 表结构
  4. 思路
  5. 参考解法
  6. 易错点

面试怎么回答

本质是「去重后按名次取值」。我会先对薪水去重,再用 DENSE_RANK 或 RANK 排名取第 N 档;放在函数里时,结果作为标量返回,不存在时自然是 NULL。如果用 LIMIT 写,要注意 MySQL 的 OFFSET 不能写表达式,得先在函数体里把 N 减一。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

题意

写一个函数,传入 N,返回员工表里第 N 高的薪水(相同薪水算同一档)。不存在第 N 高时返回 NULL。

表结构

  • Employee:Id(主键)、Salary

思路

和第二高的思路一样,只是名次变成参数。原解法先按薪水 GROUP BY 去重,再用 RANK 排名,取排名等于 N 的那一档;因为已经去重,RANK 和 DENSE_RANK 在这里结果相同。也可以在函数里先 SET N = N - 1,再用 LIMIT 1 OFFSET N,因为 MySQL 的 LIMIT 不能直接写表达式。

参考解法

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
  RETURN (
      SELECT IFNULL(
        (select salary  
        from(
        select salary,
        rank() over(order by salary desc) rk
        from Employee
        group by salary
        )t1
        where rk=N),NULL) SecondHighestSalary
  );
END

另一种写法:LIMIT 版本,先在函数里把 N 减 1

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
  SET N = N - 1;
  RETURN (
    SELECT DISTINCT Salary FROM Employee
    ORDER BY Salary DESC
    LIMIT 1 OFFSET N
  );
END

易错点

  • 没去重就用 RANK:两个并列第一时第二名会被跳过,得到错误的档位。
  • MySQL 的 LIMIT/OFFSET 不支持 N-1 这种表达式,要先在函数体里算好再用。
刷题进度保存在当前浏览器