SQL刷题从0到100,row_number解不了,那就用dense_rank(22 23 24)

328 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

大家好,我是老表,sql刷题继续更新啦,后面每次遇到困难题后就更新。

今天更新3道题,1(中等)+2(较难)。

  • SQL22 统计各个部门的工资记录数(中等)
  • SQL23 对所有员工的薪水按照salary降序进行1-N的排名(较难)
  • SQL24 获取所有非manager员工当前的薪水情况(较难)

SQL22 统计各个部门的工资记录数

我的思路: 需求搞清楚,就蛮简单了,先将部门员工表和薪水表连接,然后通过部门编号分组,计算数据条数,可以得出每个部门对应的薪水记录数,然后和部门表连起来,即可获取对应的部门名称了。

我的题解:

select a1.dept_no, b1.dept_name, a1.sum
from (
select a.dept_no, count(a.emp_no) as sum
from dept_emp as a
join salaries as b
on a.emp_no = b.emp_no
group by a.dept_no) as a1, departments as b1
where a1.dept_no = b1.dept_no
;

涉及知识点:

  • 完整sql执行顺序(每天看一遍,不信记不住):
from -> where -> group by -> having -> select -> order by -> limit
  • 窗口函数count计算分组内数据条数
  • group by 分组

提交结果:

SQL23 对所有员工的薪水按照salary降序进行1-N的排名

我的思路: 这里正好用到之前讲的窗口函数dense_rank。按题目示例我们知道,需要输出的是按薪水降序排序,生成新的一列排序序号,相同薪水排序序号相同,且按照emp_no升序排列。

因为做这题前一天才看了窗口函数相关内容,所以马上想到dense_rank,可以计算排序,相同位次一样,如:

数值:23 23 24 25
排序:1  1  2  3

我的题解:

select emp_no, salary, dense_rank() over(order by salary desc) as t_rank
from salaries
order by t_rank,emp_no;

涉及知识点:

  • 完整sql执行顺序(每天看一遍,不信记不住):
from -> where -> group by -> having -> select -> order by -> limit
  • 窗口函数 dense_rank() over(order by salary desc)
  • 顺便提一下:rank() 会跳位,比如还是上面的例子,排序会变成:1 1 3 4
  • 顺便提一下:row_number() 直接为位置序号,比如还是上面的例子,排序会变成:1 2 3 4

提交结果:

其他题解:
有点算法的意思了,下回给大家分析下,也欢迎大家评论区说说自己的看法。

SQL24 获取所有非manager员工当前的薪水情况

我的思路: 和之前的题目很相像,越往后会发现,给的表越来越多,信息还是一样,需求也一样,这样也更符合数据库范式。这里我直接从dept_emp和salaries中取出所需数据,去除部门经理即可,类似把现在的散表合并成之前的宽表,这里没有用到employees表,根据需求确实不需要。

我的题解:

-- employees 员工信息表
-- dept_emp 部门员工关系表
-- dept_manager 部门经理信息表
-- salaries 员工薪水表

select a.dept_no, a.emp_no, b.salary
from dept_emp as a,salaries as b
where a.emp_no not in (select emp_no from dept_manager)
and a.to_date = '9999-01-01'
and a.emp_no = b.emp_no
;

涉及知识点:

  • 完整sql执行顺序(每天看一遍,不信记不住):
from -> where -> group by -> having -> select -> order by -> limit
  • not in 判断元素是否在集合内

提交结果: