176. 第二高的薪水
问题链接
分析
题目要求:
查询并返回 Employee 表中第二高的薪水 。如果不存在第二高的薪水,查询应该返回 null 。
下面是示例:
查询结果如下例所示。
示例 1:
输入:
Employee 表:
+----+--------+
| id | salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+
输出:
+---------------------+
| SecondHighestSalary |
+---------------------+
| 200 |
+---------------------+
示例 2:
输入:
Employee 表:
+----+--------+
| id | salary |
+----+--------+
| 1 | 100 |
+----+--------+
输出:
+---------------------+
| SecondHighestSalary |
+---------------------+
| null |
+---------------------+
其实这道题是一个简单的排序取值问题。我们知道,在mysql内可以使用ORDER BY排序,并使用LIMIT 参数,就可以获取排序的结果。但是这道题,要求的是第2高的数据,这样简单的LIMIT就满足不了需求。我们不妨可以这样想,取第二个数据,其实就是跳过第一个数据,取下一个值。这个在mysql内,可以使用OFFSET实现。
下面我来给出解题思路:
- 使用 ORDER BY 将薪水降序排列。
- 使用 LIMIT 获取第二行的薪水。
- 如果第二行存在,则返回该薪水值;否则返回 NULL。
实现代码之前,我们来熟悉/学习一下OFFSET的使用方法
OFFSET使用方法详解
OFFSET 是 SQL 查询中用于指定结果集开始位置的子句。它通常与 LIMIT 结合使用,用于分页查询或者从指定位置开始获取数据。
从指定位置开始获取数据
SELECT column1, column2, ...
FROM table_name
OFFSET offset_value;
offset_value:要跳过的行数,即结果集开始的位置。
OFFSET 子句的取值范围是非负整数。
如果指定的 OFFSET 值大于结果集的行数,将不会返回任何行。
如果 OFFSET 的值为 0,则从结果集的第一行开始返回数据。
如果不指定 LIMIT,则 OFFSET 将从指定位置开始返回数据,直到结果集的末尾。
SELECT *
FROM students
OFFSET 2;
这个查询将会从 students 表中的第三行开始返回数据,因为 OFFSET 子句指定了要跳过的行数为 2,即跳过前两行。
看过了OFFSET的使用方法之后,我们来构造这个SQL语句
思路
要求是取第二高的薪水==>将数据倒序排列,并跳过第一个数据,取第二个数据
SELECT DISTINCT salary AS SecondHighestSalary
FROM Employee
ORDER BY salary DESC
LIMIT 1 OFFSET 1;
因为这里salary可能会重复,所以我使用DISTINCT 去重操作。
将这个语句进行测试
解答报错!😭😭😭
题目要求当没有第二高的数据时,返回NULL,但是代码执行之后没有返回数据。看来是代码出现了一些问题。
要解决这个问题其实也很容易,我们判断一下原代码的执行结果,如果没有结果就返回NULL即可。
这里可以使用子查询实现,具体代码如下:
SELECT
(SELECT DISTINCT salary
FROM Employee
ORDER BY salary DESC
LIMIT 1 OFFSET 1) AS SecondHighestSalary;
将原来的查询语句作为子查询的条件,并将结果查询出来即可。
其实我们还可以使用MYSQL里面的IFNULL函数实现,具体的代码实现如下:
SELECT
IFNULL(
(SELECT DISTINCT Salary
FROM Employee
ORDER BY Salary DESC
LIMIT 1 OFFSET 1),
NULL) AS SecondHighestSalary
当子查询结果为NULL时,我们将函数的返回结果设置为NULL再查询出来即可。
解答
我觉得简洁高效的代码还是第一个,在这里:
SELECT
(SELECT DISTINCT salary
FROM Employee
ORDER BY salary DESC
LIMIT 1 OFFSET 1) AS SecondHighestSalary;