• 【SQL屠夫系列】leetcode-176. 第二高的薪水


    在这里插入图片描述

    在如今的程序员面试过程中,考察SQL部分能力,虽不是难点,但几乎是必考.
    为检查思路盲点,避免翻船,各位看官也可以复盘下,如对你有一丝的帮助,欢迎给个赞叭~
    ps: 数据开发者,建议可以自己加难度进行考察

    leetcode难度:中等
    面试频率:中 (遇到过类似题型1次+)

    1. 题目

    1.1 表

    Employee 表:

    +-------------+------+
    | Column Name | Type |
    +-------------+------+
    | id          | int  |
    | salary      | int  |
    +-------------+------+
    id 是这个表的主键。
    表的每一行包含员工的工资信息。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1.2 需求

    编写一个 SQL 查询,获取并返回 Employee 表中第二高的薪水 。如果不存在第二高的薪水,查询应该返回 null 。

    查询结果如下例所示。

    输入:
    Employee 表:
    +----+--------+
    | id | salary |
    +----+--------+
    | 1  | 100    |
    | 2  | 200    |
    | 3  | 300    |
    +----+--------+
    输出:
    +---------------------+
    | SecondHighestSalary |
    +---------------------+
    | 200                 |
    +---------------------+
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    输入:
    Employee 表:
    +----+--------+
    | id | salary |
    +----+--------+
    | 1  | 100    |
    +----+--------+
    输出:
    +---------------------+
    | SecondHighestSalary |
    +---------------------+
    | null                |
    +---------------------+
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2. 考点分析

    第一层解法

    这道题很简单,主要考察排序+limit+偏移量的应用,很多新手可能对偏移量OFFSET 不熟,导致不好下手

    第二次解法

    pass

    第三层解法

    pass

    更多思路

    3. 开撸

    1. 第一层解法

    limit n子句表示查询结果返回前n条数据
    offset n表示跳过x条语句
    limit y offset x 分句表示查询结果跳过 x 条数据,读取前 y 条数据
    使用limit和offset,降序排列再返回第二条记录可以得到第二大的值。

    SELECT
        IFNULL(
          (SELECT DISTINCT Salary
           FROM Employee
           ORDER BY Salary DESC
            LIMIT 1 OFFSET 1),
        NULL) AS SecondHighestSalary
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    PS: 注意sql的健壮性,不要忘记IFNULL 空值的判断

    4. 扩展:第N高的薪水

    编写一个SQL查询来报告 Employee 表中第 n 高的工资。如果没有第 n 个最高工资,查询应该报告为 null 。

    输入: 
    Employee table:
    +----+--------+
    | id | salary |
    +----+--------+
    | 1  | 100    |
    | 2  | 200    |
    | 3  | 300    |
    +----+--------+
    n = 2
    输出: 
    +------------------------+
    | getNthHighestSalary(2) |
    +------------------------+
    | 200                    |
    +------------------------+
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    输入: 
    Employee 表:
    +----+--------+
    | id | salary |
    +----+--------+
    | 1  | 100    |
    +----+--------+
    n = 2
    输出: 
    +------------------------+
    | getNthHighestSalary(2) |
    +------------------------+
    | null                   |
    +------------------------+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4.1 说明

    排名是数据库中的一个经典题目,实际上又根据排名的具体细节可分为3种场景:

    连续排名,例如薪水3000、2000、2000、1000排名结果为1-2-3-4,体现同薪不同名,排名类似于编号
    同薪同名但总排名不连续,例如同样的薪水分布,排名结果为1-2-2-4
    同薪同名且总排名连续,同样的薪水排名结果为1-2-2-3
    不同的应用场景可能需要不同的排名结果,也意味着不同的查询策略。本题的目标是实现第三种排名方式下的第N个结果,且是全局排名,不存在分组的问题,实际上还要相对简单一些。

    值得一提的是:在Oracle等数据库中有窗口函数,可非常容易实现这些需求,而MySQL直到8.0版本也引入相关函数。最新OJ环境已更新至8.0版本,可直接使用窗口函数。

    4.2 思路

    这种题型最简单的就是用窗口函数来撸,当然如果为了挑战自己可以采用更多解法来玩下。

    4.3 窗口函数的解法

    实际上,在mysql8.0中有相关的内置函数,而且考虑了各种排名问题:

    • row_number(): 同薪不同名,相当于行号,例如3000、2000、2000、1000排名后为1、2、3、4
    • rank(): 同薪同名,有跳级,例如3000、2000、2000、1000排名后为1、2、2、4
    • dense_rank(): 同薪同名,无跳级,例如3000、2000、2000、1000排名后为1、2、2、3
    • ntile(): 分桶排名,即首先按桶的个数分出第一二三桶,然后各桶内从1排名,实际不是很常用

    显然,本题是要用第三个函数。
    另外这三个函数必须要要与其搭档over()配套使用,over()中的参数常见的有两个,分别是

    • partition by,按某字段切分
    • order by,与常规order by用法一致,也区分ASC(默认)和DESC,因为排名总得有个依据
      注:下面代码仅在mysql8.0以上版本可用,最新OJ已支持。
            SELECT 
                DISTINCT salary
            FROM 
                (SELECT 
                    salary, dense_rank() over(ORDER BY salary DESC) AS rnk
                 FROM 
                    employee) tmp
            WHERE rnk = N
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    作业

    关于排名的问题,你还有更好的解法吗?


    在这里插入图片描述

  • 相关阅读:
    gzip 压缩优化大 XML 响应的处理方法
    2022阿里P7级面试,掌握这份路线图上的技术点,So easy(Java岗)
    2022年,软件测试还能学吗?别学了,软件测试岗位饱和了...
    SpringMVC之CRUD和文件上传下载
    Vue 项目中的错误如何处理的?
    记一次接口优化操作
    二进制安全虚拟机Protostar靶场 安装,基础知识讲解,破解STACK ZERO
    基于springboot+vue的西藏特产销售购物商城系统 elementui
    彻底弄懂Vue的作用域插槽
    vue3引入three.js
  • 原文地址:https://blog.csdn.net/qq_31557939/article/details/126697436