问题:spa
The Employee
table holds all employees. Every employee has an Id, and there is also a column for the department Id..net
+----+-------+--------+--------------+ | Id | Name | Salary | DepartmentId | +----+-------+--------+--------------+ | 1 | Joe | 70000 | 1 | | 2 | Henry | 80000 | 2 | | 3 | Sam | 60000 | 2 | | 4 | Max | 90000 | 1 | | 5 | Janet | 69000 | 1 | | 6 | Randy | 85000 | 1 | +----+-------+--------+--------------+
The Department
table holds all departments of the company.code
+----+----------+ | Id | Name | +----+----------+ | 1 | IT | | 2 | Sales | +----+----------+
Write a SQL query to find employees who earn the top three salaries in each of the department. For the above tables, your SQL query should return the following rows.排序
+------------+----------+--------+ | Department | Employee | Salary | +------------+----------+--------+ | IT | Max | 90000 | | IT | Randy | 85000 | | IT | Joe | 70000 | | Sales | Henry | 80000 | | Sales | Sam | 60000 | +------------+----------+--------+
解决:three
① 使用Select Count(Distinct),内交Employee和Department两张表,而后咱们找出比当前薪水高的最多只能有两个,那么前三高的都能被取出来了。2360 msget
SELECT d.Name Department,e.Name Employee,e.Salary Salary
FROM Employee e JOIN Department d ON e.DepartmentId = d.Id
WHERE
(SELECT COUNT(DISTINCT Salary)
FROM Employee
WHERE Salary > e.Salary AND DepartmentId = d.Id) < 3
ORDER BY d.Name,e.Salary DESC;/*最多取出比当前值大的两个数值,按照部门名递增的顺序,工资递减的顺序排序*/it
② 将上面方法中的<3换成了IN (0, 1, 2)。1608 mstable
SELECT d.Name Department,e.Name Employee,e.Salary Salary
FROM Employee e,Department d
WHERE
(SELECT COUNT(DISTINCT Salary) FROM Employee
WHERE Salary > e.Salary AND DepartmentId = d.Id) IN (0,1,2)
AND e.DepartmentId = d.Id
ORDER BY d.Name,e.Salary DESC;方法
③ 使用Group by Having Count(Distinct ..) 关键字。1353 ms。top
SELECT d.Name Department,e.Name Employee,e.Salary Salary
FROM
(SELECT e1.Name,e1.Salary,e1.DepartmentId
FROM Employee e1 JOIN Employee e2 ON e1.DepartmentId = e2.DepartmentId AND e1.Salary <= e2.Salary
GROUP BY e1.Id
HAVING COUNT(DISTINCT e2.Salary) <= 3) e
JOIN Department d ON e.DepartmentId = d.Id
ORDER BY d.Name,e.Salary DESC;/*使用自链接先取出前三个最大的工资,而后取出其所须要的内容*/
④ 给每一个人都按照薪水的高低增长一个rank,最后返回rank值小于等于3的项便可。1671 ms
SELECT d.Name AS Department, e.Name AS Employee, e.Salary FROM
(SELECT Name, Salary, DepartmentId,
@rank := IF(@pre_d = DepartmentId, @rank + (@pre_s <> Salary), 1) AS rank, @pre_d := DepartmentId, @pre_s := Salary FROM Employee, (SELECT @pre_d := -1, @pre_s := -1, @rank := 1) AS init ORDER BY DepartmentId, Salary DESC) e JOIN Department d ON e.DepartmentId = d.Id WHERE e.rank <= 3 ORDER BY d.Name, e.Salary DESC;