The Employee
table holds all employees. Every employee has an Id, and there is also a column for the department Id.spa
+----+-------+--------+--------------+ | 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.blog
+------------+----------+--------+ | Department | Employee | Salary | +------------+----------+--------+ | IT | Max | 90000 | | IT | Randy | 85000 | | IT | Joe | 70000 | | Sales | Henry | 80000 | | Sales | Sam | 60000 | +------------+----------+--------+
這個題目屬於hard級別,難點在於先組內排序,而後取組內前三的數據出來(排名可並列),最後再作一個組間排序。排序
所以,個人解題思路是這樣的:three
1.把數據按照DepartmentId,Salary 排序,這樣的話同一部門的數據在搜索的結果集中就在一塊兒。ci
select DepartmentId, Name ,Salary from Employee order by DepartmentId ,Salary desc
2.對同一部門的數據的記錄進行編號,從1開始,若是和上一行的薪水相同,則編號和上一行同樣。it
select DepartmentId, Salary,Name, @num := if(@cid = DepartmentId ,if(@cursalry != Salary, @num + 1,@num), 1) as number, @maxprice := if(@num = 1 ,@maxprice := Salary,@maxprice) as mp, @cid := DepartmentId as dummy, @cursalry:= Salary as curs from (select DepartmentId, Name ,Salary from Employee order by DepartmentId ,Salary desc) e ,(select @num := 0,@maxprice := 0,@cid := 0,@cursalry = 0) b ) c
3.過濾掉編號大於 3的記錄。由於數據已經排序過,因此編號小於等於3的記錄就是薪水的前三名。table
select c.DepartmentId, c.Name ,c.Salary from ( select DepartmentId, Salary,Name, @num := if(@cid = DepartmentId ,if(@cursalry != Salary, @num + 1,@num), 1) as number, @maxprice := if(@num = 1 ,@maxprice := Salary,@maxprice) as mp, @cid := DepartmentId as dummy, @cursalry:= Salary as curs from (select DepartmentId, Name ,Salary from Employee order by DepartmentId ,Salary desc) e ,(select @num := 0,@maxprice := 0,@cid := 0,@cursalry = 0) b ) c where c.number <=3 ) g
4.關聯Department表,獲取Department Name。class
select f.Name as Department ,g.Name as Employee ,g.Salary from ( select c.DepartmentId, c.Name ,c.Salary from ( select DepartmentId, Salary,Name, @num := if(@cid = DepartmentId ,if(@cursalry != Salary, @num + 1,@num), 1) as number, @maxprice := if(@num = 1 ,@maxprice := Salary,@maxprice) as mp, @cid := DepartmentId as dummy, @cursalry:= Salary as curs from (select DepartmentId, Name ,Salary from Employee order by DepartmentId ,Salary desc) e ,(select @num := 0,@maxprice := 0,@cid := 0,@cursalry = 0) b ) c where c.number <=3 ) g ,Department f where g.DepartmentId = f.Id ;