SQL练习:第二高的薪水——Distinct 和 Limit 的执行顺序
题目:第二高的薪水——LeetCode
答案:官方答案解析
题目:
编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 。
Id | Salary |
---|---|
1 | 100 |
2 | 200 |
3 | 300 |
例如上述 Employee 表,SQL查询应该返回 200 作为第二高的薪水。如果不存在第二高的薪水,那么查询应返回 null。
SecondHighestSalary |
---|
200 |
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/second-highest-salary
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解析
Sql Server:(方法一)
思路: 先取得列表中Salary的最大值,然后在列表小于最大值的部分里取最大值,即得到第二高薪酬。
/* Write your T-SQL query statement below */
select max(Salary) as "SecondHighestSalary"
from Employee
where Salary < (select max(Salary) from Employee)
方法优点:属于标准SQL语言,各数据库服务器通用
方法缺点:运行速度很慢,跟limit和offset连用比起来,相差一个数量级。
MySQL:(方法二)
思路: 先对列表进行降序,然后使用LIMIT 1, 1,直接取得列表中的第二位。同时,由于题目要求“如果不存在第二高的薪水,那么查询应返回 null”,因此在最后结果上套用IFNULL函数。
SELECT
IFNULL(
(SELECT DISTINCT Salary
FROM Employee
ORDER BY Salary DESC
LIMIT 1, 1),
NULL) AS SecondHighestSalary
Distinct 和 Limit 的执行顺序
在使用MySQL解答题目的时候发现,代码中不加入DISTINCT(位于方法二的第三行),则提示解答错误;加入DISTINCT,则提交通过。刚开始一直无法理解差别在哪儿,后来发现与LIMIT 的使用方法,以及Distinct 和 Limit 的执行顺序有关。
LIMIT语句 (LIMIT i, n): 查询n条数据,索引从i 到 i+n-1,第 i+1条记录到第 i+n条记录。i:为查询结果的索引值(默认从0开始),当i=0时可省略 i。因此 LIMIT 1, 1的意思是,从第二行开始取数据,一共取一条数据。
Distinct 和 Limit 的执行顺序:Distinct 和 Order BY语句先执行, Limit最后执行。
当仅有一个ID拥有第一高薪水时,加Distinct 与不加,返回的结果是相同的。当有两个及以上ID拥有第一高薪水时,两者存在区别。
此时,不使用Distinct意味着不去重直接排序,数据的前两条均为第一高薪水,LIMIT1, 1 从第二行开始取,由于第二条依旧是最高的薪水,那么取到的记录仍未第一高薪水,而不是第二高薪水。使用Distinct,即去重并排序后,数据中第一高薪水仅占一条,第二条即为第二高薪水,则取出的为第二高薪水数据。