简说Python,号主老表,Python终身学习者,数据分析爱好者,从18年开始分享Python知识,原创文章227篇,写过Python、SQL、Excel入门文章,也写过Web开发、数据分析文章,老表还总结整理了一份2022Python学习资料和电子书资源,关注后私信回复:2022 即可领取。
SQL18 获取当前薪水第二多的员工的emp_no以及其对应的薪水salary
我的思路: 紧接上一题,和sql17的区别就是 将员工薪水另外存了一张表,另外要求不能使用order by 排序。我们可以先找出薪水表中第二高的薪水,然后从employees、salaries两表中筛选出薪水第二高的员工信息。
取第二高的薪水,这里采用的是去除当前最高薪水后,再查找剩余薪水中的最高薪水。
我的题解:
select a.emp_no, b.salary, a.last_name, a.first_name from employees as a join salaries as b on a.emp_no = b.emp_no and b.salary = ( select max(salary) from salaries where to_date = '9999-01-01' and salary < ( select max(salary) from salaries where to_date = '9999-01-01' ) ) ;
涉及知识点:
- 完整sql执行顺序(每天看一遍,不信记不住):
from -> where -> group by -> having -> select -> order by -> limit
- 窗口函数max取最大值
提交结果:
其他题解:
这里有个大神三玫
提供了另外一种找第二高薪水的方法,通过salaries自连接,连接条件是s1.salary <= s2.salary
,这样后,再根据s1.salary
分组,然后count(distinct s2.salary) = 2
就是第二高薪水。
select a.emp_no, b.salary, a.last_name, a.first_name from employees as a join salaries as b on a.emp_no = b.emp_no and b.salary = ( select s1.salary from salaries as s1 join salaries as s2 on s1.salary <= s2.salary and s1.to_date = s2.to_date and s1.to_date = '9999-01-01' group by s1.salary having count(distinct s2.salary) = 2 ) ;
这个思路真的特别巧妙,刚开始你可能会比较懵,不知道为什么这样就可以筛选出第二高薪水了,但是你一画图,举例子操作下,瞬间就能明白。
这里的原理可以归纳为:大于等于自己的数值的个数一定等于自己的降序排序的位数。
例如:在集合{100,98,97,89}中,大于等于98的只有100,98,所以98在这个集合中必然是第二大的数。
评论区也有人做了效率对比,当数据量上升时,该方法效率会大大降低,其实原因也很简单,salaries变大,自连接自然会消耗大量时间。
SQL19 查找所有员工的last_name和first_name以及对应的dept_name
我的思路: 这个题目和sql5是类似的,现在多了一个departments表,输出里把dept_no改成了dept_name,所以在原来的解法中,dept_emp表先与departmentsjoin,然后再和employees连接即可。
我的题解:
select a.last_name, a.first_name, b.dept_name from ( select emp_no, last_name, first_name from employees) as a left join ( select d1.emp_no, d2.dept_name from dept_emp as d1 join departments as d2 on d1.dept_no = d2.dept_no ) as b on b.emp_no = a.emp_no ;
涉及知识点:
- 完整sql执行顺序(每天看一遍,不信记不住):
from -> where -> group by -> having -> select -> order by -> limit
- left join
提交结果:
SQL21 查找在职员工自入职以来的薪水涨幅情况
我的思路: 这里需要求每个在职员工从入职开始到现在的薪水涨幅情况,这里直接找出每个在职员工入职时薪水,和当前薪水,然后求差即可。
这题比较有意思的是需要理解清楚以下几个日期字段含义:
- employees.hire_date:表示雇佣日期,可以理解为入职日期;
- salaries.from_date:表示薪水开始时间;
- salaries.to_date:表示薪水结束时间,如果为9999-01-01,则表示为当前在职员工。
我的题解:
select s1.emp_no, (s2.salary-s1.salary) as growth from ( -- 入职薪水 select a1.emp_no, a2.salary from employees as a1 join salaries as a2 on a1.emp_no = a2.emp_no and a1.hire_date = a2.from_date ) as s1 join ( -- 当前薪水 select emp_no, salary from salaries where to_date = '9999-01-01' ) as s2 on s1.emp_no = s2.emp_no order by growth ;
涉及知识点:
- 完整sql执行顺序(每天看一遍,不信记不住):
from -> where -> group by -> having -> select -> order by -> limit
- join 连接
- order by 分组
提交结果: