免费教程《图解 SQL 面试题》
  • 图解 SQL 面试题
  • 第 1 章:简单查询
  • 图解面试题:如何查找重复数据?
  • 第 2 章:复杂查询
    • 图解面试题:如何查找第 N 高的数据?
  • 第 3 章 多表查询?
    • 图解面试题:多表如何查询?
    • 图解面试题:如何查找不在表里的数据?
    • 图解面试题:你有多久没涨过工资了?
    • 图解面试题:如何比较日期数据?
    • 图解面试题:如何交换数据?
    • 滴滴 2020 年面试题:如何找出最小的 N 个数?
    • 图解面试题:行列互换问题,怎么办?
    • 图解面试题:找出连续出现 N 次的内容?
    • 链家面试题:如何分析留存率?
  • 第 4 章
    • 拼多多面试题:如何查找前 20% 的数据?
    • 图解面试题:如何查找工资前三高的员工
    • 图解面试题:如何分组比较?
    • 图解面试题:双 11 用户如何分析?
    • 图解面试题:如何分析游戏?
  • 第 5 章:项目实战
    • 图解面试题:滴滴 2020 求职真题
    • 滴滴面试题:打车业务问题如何分析?
    • 电商面试题:如何分析复杂业务?
    • 图解面试题:如何分析用户满意度?
    • 图解面试题:如何分析红包领取情况?
    • 图解面试题:如何分析中位数?
    • 小红书面试题:如何分析用户行为?
    • 教育行业案例:学员续费如何分析?
    • 字节跳动面试题:你的平均薪水是多少?
Powered by GitBook
On this page

Was this helpful?

  1. 第 4 章

图解面试题:如何查找工资前三高的员工

Previous拼多多面试题:如何查找前 20% 的数据?Next图解面试题:如何分组比较?

Last updated 4 years ago

Was this helpful?

【题目】

“成绩表” 记录了学生的学号,学生选修的课程,以及对应课程的成绩。

为了对学生成绩进行考核,现需要查询每门课程的前 3 高成绩。

注意:如果出现并列第一的情况,则同为第一名。

【解题思路】

题目要求找出每个课程获得前三高成绩的所有学生。难点在于每个课程前 3 高成绩。

前 3 高的成绩意味着要对成绩排名。

专用窗口函数 rank, dense_rank, row_number 有什么区别呢?

它们的区别我举个例子,你们一下就能看懂:

select *,
   rank() over (order by 成绩 desc) as ranking,
   dense_rank() over (order by 成绩 desc) as dese_rank,
   row_number() over (order by 成绩 desc) as row_num
from 班级;

得到结果:

从上面的结果可以看出:

rank 函数:这个例子中是 5 位,5 位,5 位,8 位,也就是如果有并列名次的行,会占用下一名次的位置。比如正常排名是 1,2,3,4,但是现在前 3 名是并列的名次,结果是:1,1,1,4。

dense_rank 函数:这个例子中是 5 位,5 位,5 位,6 位,也就是如果有并列名次的行,不占用下一名次的位置。比如正常排名是 1,2,3,4,但是现在前 3 名是并列的名次,结果是:1,1,1,2。

row_number 函数:这个例子中是 5 位,6 位,7 位,8 位,也就是不考虑并列名次的情况。比如前 3 名是并列的名次,排名是正常的 1,2,3,4。

这三个函数的区别如下:

题目要求 “如果出现并列第一的情况,则同为第一名”。所以,我们使用窗口函数 dense_rank。

步骤一:按课程分组 (partiotion by 课程号),并按成绩降序排列 (order by 成绩 desc),套入窗口函数的语法,就是下面的 sql 语句:

select *,
     dense_rank() over(partition by 课程号
                       order by 成绩 desc) as排名
from 成绩表;

运行结果如下:

步骤二:筛选出前 3 高的成绩,所以我们在上一步基础上加入一个 where 字句来筛选出符合条件的数据。(where 排名 <=3)

select 课程号,学号,成绩,排名 from
(select *,
     dense_rank() over (partition by 课程号
                  order by 成绩 desc) as 排名
from 成绩表) as aa
where 排名 <=3;

【本题考点】

1)考察如何使用窗口函数及专用窗口函数排名的区别:rank, dense_rank, row_number

2)经典 topN 问题:每组最大的 N 条记录。这类问题涉及到 “既要分组,又要排序” 的情况,要能想到用窗口函数来实现。

# topN问题 sql模板
select *
from (
   select *, 
          row_number() over (partition by 要分组的列名
                       order by 要排序的列名 desc) as 排名
   from 表名) as a
where 排名 <= N;

【举一反三】

Employee 表包含所有员工信息,每个员工有其对应的工号 (Id),姓名 (Name),工资 (Salary) 和部门编号 ( DepartmentId) 。

查找每个部门前三高工资的员工。例如,根据上述给定的表,查询结果应返回:

参考答案:

select DepartmentId,Name,Salary
from (
   select *, 
          dense_rank() over (partition by DepartmentId
                       order by Salary desc) as ranking
   from Employee) as a
where ranking <= 3;

这种题类型其实是 “分组排名”,遇到这类型题就要想到用里讲过的窗口函数。

推荐:

《猴子 从零学会 sql》
如何从零学会 sql?