力扣刷题——高频SQL50题:
题目链接:https://leetcode.cn/problems/department-top-three-salaries/?envType=study-plan-v2&envId=sql-free-50
185. 部门工资前三高的所有员工:
表:
Employee: Department
+--------------+---------+ +-------------+---------+
| Column Name | Type | | Column Name | Type |
+--------------+---------+ +-------------+---------+
| id | int | | id | int |
| name | varchar | | name | varchar |
| salary | int | +-------------+---------+
| departmentId | int |
+--------------+---------+
id 是该表的主键列(具有唯一值的列)。 id 是该表的主键列(具有唯一值的列)。
departmentId 是 Department 表中 ID 的外键(reference 列)。 该表的每一行表示部门ID和部门名。
该表的每一行都表示员工的ID、姓名和工资。它还包含了他们部门的ID。
公司的主管们感兴趣的是公司每个部门中谁赚的钱最多。一个部门的高收入者是指一个员工的工资在该部门的不同工资中排名前三。
编写解决方案,找出每个部门中收入高的员工。
以任意顺序返回结果表。
返回结果格式如下所示。
Employee 表: Department 表: 输出:
+----+-------+--------+--------------+ +----+-------+ +------------+----------+--------+
| id | name | salary | departmentId | | id | name | | Department | Employee | Salary |
+----+-------+--------+--------------+ +----+-------+ +------------+----------+--------+
| 1 | Joe | 85000 | 1 | | 1 | IT | | IT | Max | 90000 |
| 2 | Henry | 80000 | 2 | | 2 | Sales | | IT | Joe | 85000 |
| 3 | Sam | 60000 | 2 | +----+-------+ | IT | Randy | 85000 |
| 4 | Max | 90000 | 1 | | IT | Will | 70000 |
| 5 | Janet | 69000 | 1 | | Sales | Henry | 80000 |
| 6 | Randy | 85000 | 1 | | Sales | Sam | 60000 |
| 7 | Will | 70000 | 1 | +------------+----------+--------+
+----+-------+--------+--------------+
先找出每个department部门分组中的薪水排名前三的员工,再使用子查询进行处理:
一般解决方法:
select d.name as Department,e.name as Employee ,e.Salary
from Employee e,Department d
where e.departmentId = d.id(+)
and e.id in (select s1.id from Employee s1,Employee s2
where s1.departmentId = s2.departmentId
and s1.Salary <= s2.Salary
group by s1.id
having count(distinct s2.Salary) <= 3)
and e.departmentId in (select id from Department);
使用开窗函数直接获取:
select aa.Department,aa.Employee,aa.salary
from (
select t2.name as Department,t1.name as Employee,t1.salary ,
dense_rank() over(partition by departmentId order by salary desc) as rk
from Employee t1,Department t2
where t1.departmentId = t2.id) aa
where aa.rk <=3;
聚合函数用得好,能省下很大功夫,介绍一下这个开窗函数:
【语法】:
rank() over(partition by column order by column desc)
dense_rank() over(partition by column1 order by column2 asc)
【参数】:
dense_rank() over() 是固定写法;
partition by 是可选参数,用于指定分区的列,类似select中的group by 子句;
order by 用于指定排序的列,类似于 order by子句;
【功能】:
计算一组数值中的排序值
【区别】:
dense_rank() 在遇到并列关系时,相关等级不会跳过;rank() 则是直接跳过该等级;
dense_rank() 是连续排序,有两个第二名时仍然跟着第三名;
rank() 是跳跃排序,有两个第二名时,接下来是第四名;