解題思路 全局排名,不分組,所以我們可以用ORDER BY排序加LIMIT N,M限制(M表示在限制條數之后的offset記錄,LIMIT M OFFSET N),排名第N高意思是LIMIT N-1,1,但是LIMIT后面只接受正整數或者單一變量,不能用表達式,所以在函數中需要先SET N = N - 1 同薪同名且連續排名,意味著需要去重,我們可以用GROUP BY 按薪水分組后再ORDER BY或者DISTINCT去重。
CREATEFUNCTION getNHighestSalary(N INT)RETURNSINTBEGINSET N := N-1;IF(N <0)THENRETURNNULL;ELSERETURN(SELECTDISTINCT salary FROM employee-- GROUP BY salaryORDERBY salary DESCLIMIT N,1);ENDIF;END
SELECTd.Name AS'Department', e1.Name AS'Employee', e1.SalaryFROM Employee e1RIGHTJOIN Department d ON e1.DepartmentId = d.IdWHERE3>(SELECTCOUNT(DISTINCT e2.Salary)FROM Employee e2WHERE e2.Salary > e1.SalaryAND e1.DepartmentId = e2.DepartmentId)GROUPBY e1.SalaryORDERBY d.`Name`, e1.Salary DESC;
連接查詢
解題思路 能用子查詢解決的問題一般都能用連接來解決
代碼示例
SELECTd.name as department, e1.name as employee, e1.salary as salaryFROMDepartment d LEFTJOIN Employee e1 on d.id = e1.departmentidLEFTJOIN Employee e2 on e1.departmentid = e2.departmentid and e1.salary<=e2.salaryGROUPBY d.name, e1.SalaryHAVINGcount(distinct e2.salary)<4ORDERBYd.name, e1.salary DESC
SELECTd. NAME department,t. NAME employee,salaryFROM(SELECT*,@r :=IF(DepartmentId =@d,IF(Salary =@s,@r,@r+1),1)AS rnk,@d := DepartmentId,@s := SalaryFROM employee,(SELECT@s :=NULL,@d :=NULL,@r :=0) initORDERBY DepartmentId, Salary DESC) tRIGHTJOIN department d ON t.DepartmentId = d.IdWHERE t.rnk <= N OR t.rnk ISNULLGROUPBY d.`Name`, salaryORDERBY DepartmentId, Salary DESC
開窗函數
解題思路 又到了快樂的開窗函數,因為是同薪同名,連續排名,所以還是用DENSE_RANK(),因為求的是部門前N高薪水,所以按部門分組再按薪水排序,那么開窗函數的使用就是:DENSE_RANK() OVER(PARTITION BY departmentid ORDER BY salary DESC) 。
代碼示例
SELECTd.`Name`, tmp.`Name`, tmp.Salary FROM(SELECT e1.DepartmentId, e1.`Name`, e1.Salary,DENSE_RANK()OVER(PARTITIONBY e1.DepartmentId ORDERBY e1.Salary DESC) rnkFROM employee e1 ) tmpRIGHTJOIN department dON d.Id = tmp.DepartmentIdWHERE rnk <= N OR t.rnk ISNULLGROUPBY d.name, tmp.Salary;