题解 | #获取每个部门中当前员工薪水最高的相关信息#
获取每个部门中当前员工薪水最高的相关信息
https://www.nowcoder.com/practice/4a052e3e1df5435880d4353eb18a91c6
感觉:老实说这道题不能叫困难
这道题用窗口函数会更加方便简洁(当然单纯用聚合也是可以完成的),所以先稍微说下窗口函数是什么东东?
窗口函数,它能在不影响当前语句(即不加任何筛选,分组等)的情况下去实时分析处理数据。因为这个特性,它必须写在select子句中。基本格式如下:
sum(money) over(partition by users) # 即 聚合函数 over ([partition by xxx] [order by xxx]) # partition by 的作用类似于 group by
更详细的介绍和用法例子在链接,大家可前往深入了解。
那么我们回到这道题当中,需求是获取每个部门中当前员工薪水最高的相关信息,结果按照部门编号dept_no升序排列
注意四个红色标识
当前:一开始对from_date和to_date置之不理,觉得好像对题目没啥太大帮助,而且在不用这些字段写出的SQL语句既然过了(就说妙不妙,hh)。但后面仔细想了下,员工表的dept_emp的from_date和to_date其实是任职时间段,只有当to_date为9999-01-01即为在职。
每个部门最高:那么意味着要通过dept_no字段分组,在通过比较salary字段获取最大值
dept_no升序:这个最快理解啦,就是用order by dept_no就完事啦~
理清楚需求标识之后,那么就开始写SQL语句啦
(1)我们先从每个部门最高这个标识下手。此时我们先不考虑该员工是否在职哈
因为dept_no和salary分别在不同的表,且每个员工都有一条对应的薪水信息,因此用连接先行关联起来(left / right join)
select a.emp_no, dept_no, salary, from dept_emp as a left join salaries as b using(emp_no)
然后我们就得考虑怎么取每个部门的最大薪水啦,这里就用到了刚刚提到的窗口函数之排序接口啦,这里罗列出三个常用的排序窗口接口
row_number (按顺序编号——1,2,3,4,5)
rank(按照规则排名。遇到同分,它是跳跃的、间断的排名,例如两个并列第一名后,下一个是第三名——1,2,2,4,5)
dense_rank(按照规则排名。排序数字是连续的、不间断。当有相同的分数时,它们的排名结果是并列的——1,2,2,3,4)
这里我们用哪个都可以,hh,我选用的是row_number
select a.emp_no, dept_no, salary, ROW_NUMBER() over(partition by dept_no order by salary desc) as sal_idx from dept_emp as a left join salaries as b using(emp_no)
稍微说明下窗口函数的作用,它是通过dept_no分组然后在组内从大到小对salary进行排序,最后贴上编号作为一个临时字段
这样我们就很清楚知道每个部门内各个员工薪水的排名啦~
至此第一个红色标识完成啦
(2)我们接着解决当前这个红色标识
其实在(1)的SQL语句中添加即可
where a.date = '9999-01-01'
(3)最后只剩下dept_no升序这个红色标识啦
在(1)那里留下了一个问题,即还未取出每个部门薪水最高的员工信息,我们在这里完结
方案是(1)和(2)的SQL语句组装成临时表,当编号为1时便是每个部门薪水最高的员工啦。再加上order by 即可完结
最终代码如下:
select dept_no, emp_no, salary from( select a.emp_no, dept_no, salary, ROW_NUMBER() over(partition by dept_no order by salary desc) as sal_idx from dept_emp as a left join salaries as b using(emp_no) where a.to_date = '9999-01-01' ) as t where sal_idx = 1 order by dept_no