题目类型:MySql
力扣上的一道算法题,也是看了评论区的大神解析后才知晓怎么做。可以拓展为分组查询前几的数据。
问题:
有两张表,一张员工表(Employee),一张部门表(Department),查各个部门前三的薪资的部门名字+员工信息
自己的想法:
①先按照各个部门进行分组,再在各个部门中按照薪水进行排序,最后再找出各个部门中薪资排名前三的数据
②实现
select Department, Employee, Salary
from(
select d.Name Department, e.Name Employee, e.Salary as Salary,
dense_rank() over ( partition by DepartmentId order by Salary desc) r
from Employee as e, Department as d where d.Id = e.DepartmentId) t
where r<=3;
③后面我也用其他的函数试了一下,发现(以上面sql语句进行测试)
/**
* 排序函数,它是在每一条数据前加上一个序号,
* 缺点:若是出现相同的数据的情况就会出现问题,因为只获取到前三条数据
* 假设薪资前三的数据是 9000(1) 8500(2) 8500(3) 7000(4) 只获取了前三条
*/
row_number()
/**
* rank的排序方式是如果出现薪资相同的情况下,它们排序数字是一样的
* 假设薪资前三的数据是 9000(1) 8500(2) 8500(2) 7000(4)
* 因为rank是跳跃式的排序方式,所以还是会出现问题
*/
rank()
/**
* dense_rank的排序方式和rank差不多,区别就是它的排序是连续性的
* 假设薪资前三的数据是 9000(1) 8500(2) 8500(2) 7000(3)
*/
dense_rank()
/**
* 这个函数可以理解成分区或者分组,但是我感觉好像有点像随机的
* NTILE(1) 将查询到的数据分为同一个区 1
* NTILE(2) 将查询到的数据分为两个区 1 2
*/
NTILE()
分享:
分享一个大佬的做法:
①找出各个部门的前三个,也就是说部门id一样,然后薪资大于某一个薪资的只有两个,加上这个“某一个”就是三个。先查找出这三个薪资的id集。此处有一个关键点就是去重,而且去重是得去掉薪水重复的,但是其实id是没有被去掉的。
select e1.Id from Employee e1 left join Employee e2 on e1.DepartmentId = e2.DepartmentId and e1.Salary<e2.Salary group by e1.Id having count(distinct e2.Salary)<=2
②将①中查询获取的id集进行查询即可,此处记得对比department的id需要在部门表中存在,因为测试用例中可能存在部门表中并没有部门信息存在,导致报错。其中根据部门id进行升序,按照薪水进行降序
select d.Name Department,e.Name Employee,e.Salary Salary from Employee e left join Department d on e.DepartmentId = d.Id where e.Id in
(①)
and e.DepartmentId in (select Id from Department) order by d.Id asc,e.Salary desc