题目链接:点击打开链接
题目大意:略。
解题思路:
- 解决方案(1):因为题目说最多 3 个,所以从最里面的子查询到最外面子查询开始,分别获取 MAX 薪水并且要排除掉上一次最高的薪水,这样从里到外子查询薪水依次排名:1、2、3名次;结尾只要包含其中一列的 S* 说明就在这排名范围内。这里尤其注意 GROUP BY 的时候,一定要对最里面的子查询的部门 Id 进行分组,因为很有可能,只有一条记录,根本没排名 2、3,这样的话对当前子查询进行部门 Id 分组的话,此时该部门 Id 为 null,就会出问题。
- 解决方案(2):在解决方案(1)的基础上,里面 3 个子查询走完其实长这样的,如图所示(当然这里的 S3/D3 为 null 是因为我的案例只有最多到排名 2 就结束了)
其实到这里可以转成 S/D 两列,这样的话到时候外围 SELECT 只要用 IN 语法就可以大功告成了,但是这里目前只想到 UNION ALL 语法进行拼接,而且很麻烦,效率低,因为要对 3 个子查询进行每次的 UNION ALL,所以这里不推荐,但是这个思路还是可以跟大伙分析下哈~
- 解决方案(3):根据 部门 (升),薪水 (降) 顺序查询出每个部门的员工薪水进行排序,注意这里的 CASE WHEN THEN 语法后面虽然没BREAK 但是默认有该作用,所以哪怕第一个 WHEN 通过后,也不会走第二个 WHEN
- 解决方案(4):公司里前 3 高的薪水意味着有不超过 3 个工资比这些值大
AC 代码
- 解决方案(1)
SELECTde. NAMEDepartment, em. NAMEEmployee, em.SalaryFROMEmployeeemJOINDepartmentdeONem.DepartmentId=de.Id, ( SELECTMAX(Salary) S3, S2, S1, DFROMEmployeee1RIGHTJOIN ( SELECTMAX(Salary) S2, S1, DFROMEmployeee0RIGHTJOIN ( SELECTMAX(Salary) S1, DepartmentIdDFROMEmployeeGROUPBYDepartmentId ) rs1ONe0.DepartmentId=rs1.DANDe0.Salary<>rs1.S1GROUPBYD ) rs2ONe1.DepartmentId=rs2.DANDe1.Salary<>rs2.S1ANDe1.Salary<>rs2.S2GROUPBYD) rs3WHEREde.Id=rs3.DAND (em.Salary=rs3.S1ORem.Salary=rs3.S2ORem.Salary=rs3.S3)
- 解决方案(2)
UNIONALL
- 解决方案(3)
SELECTdep.NameDepartment, emp.NameEmployee, emp.SalaryFROM ( SELECTte.DepartmentId, te.Salary, CASEWHEN=DepartmentIdTHEN :=+1WHEN :=DepartmentIdTHEN :=1ENDAS`RANK`FROM (SELECT :=null, :=0) tt, ( SELECTDepartmentId,SalaryFROMEmployeeGROUPBYDepartmentId,SalaryORDERBYDepartmentId,SalaryDESC ) te ) tINNERJOINDepartmentdepONt.DepartmentId=dep.IdINNERJOINEmployeeempONt.DepartmentId=emp.DepartmentIdandt.Salary=emp.Salaryandt.RANK<=3
- 解决方案(4)
SELECTd.NameAS'Department', e1.NameAS'Employee', e1.SalaryFROMEmployeee1JOINDepartmentdONe1.DepartmentId=d.IdWHERE3> (SELECTCOUNT(DISTINCTe2.Salary) FROMEmployeee2WHEREe2.Salary>e1.SalaryANDe1.DepartmentId=e2.DepartmentId ) ;