185. Department Top Three Salaries

题目:

Employee 有所有员工信息,包括Id,薪水和所属部门Id。

IdNameSalaryDepartmentId
1Joe700001
2Henry800002
3Sam600002
4Max900001
5Janet690001
6Randy850001

公司部门信息表Department

IdName
1IT
2Sales

找出每个部门薪水排前三的员工信息。如果薪水相同则并列。
例如:

DepartmentEmployeeSalary
ITMax90000
ITRandy85000
ITJoe70000
SalesHenry80000
SalesSam60000

解析:

题中有两张表,第一步先连接。

select 
    dd.Name as Department, 
    ee.Name as Employee,
    ee.Salary as Salary
from Employee ee, Department dd
where ee.DepartmentId =dd.id 
...

as标注出正确的表头。
接下来是条件部分,本题虽然看上去有分组(按部门分组取前三)但是如果使用group by取前三的操作其实很困难,使用group by后的排列顺去很难控制,因此在这里可以使用一个巧妙地方法,该方法同样适用于“找出最高(低)的前n项”一类问题。

(
select 
    count(distinct ee2.salary) 
from 
    employee ee2 
where 
    ee.DepartmentId=ee2.DepartmentId and ee.salary<ee2.salary
)<=2

思路为,将employee做自连接。注意这里的连接方式,ee.DepartmentId=ee2.DepartmentId,这样连接后两个表中的数据行并不是一对一的关系,原因在于DepartmentId重复多个,并没有唯一标识。这样做每一个员工分别和其同部门的所有员工组成多个数据行。
拿个别的例子:

namesexagetelnamesexagetel
周周3017754585545周周3017754585545
张三5411012121122周周3017754585545
王五1817722454565周周3017754585545
赵六1818922454565周周3017754585545
孙七3010522454565孙七3010522454565
李四2013522454565孙七3010522454565

这里是按照性别分的类,可以看出周周和其他所有男人分别组成了4行数据。

这是连接表的方式,检索的方式则是
ee.salary<ee2.salary
当我们拿到形如上个例子那样的表后,每一类下的大小就很容易比较了(因为已经有了同类之间所有组合的数据行了)。

如果某个ee.salary员工的薪水是同类最高的,那么在经过
ee.salary<ee2.salary
这样的比较后会发现,并不存在某一个员工他的薪水比这个最高薪水还要高的,那么在select count()获取到的总数即为0。
同样,如果员工薪水是次高的,那么只会有一个人的薪水比他高,因此select count()获取到的数为1。
不难看出第三高薪水的员工最后计数则为2。
因此,只要是select count()计数小于等于2的都是前三高的数。

注意:这里要注意的是实际使用中使用的是select count(distinct salary)主要是因为salary相同的排名并列。因此,前三高的数并不只有3个,有可能是4个(有两个薪水并列)或者更多。

综上所述,最终的SQL查找语句为:

select 
    dd.Name as Department, 
    ee.Name as Employee,
    ee.Salary as Salary
from Employee ee, Department dd
where ee.DepartmentId =dd.id 
and
    (
    select 
        count(distinct ee2.salary) 
    from 
        employee ee2 
    where 
        ee.DepartmentId=ee2.DepartmentId and ee.salary<ee2.salary
    )<=2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值