牛客网SQL刷题复盘(1)

牛客网SQL刷题复盘

Q1 查找最晚入职员工的所有信息

数据:employees

关键:找到hire_date最大值

简单的order by与limit可以做到,但如果最晚入职的员工有两人及以上,那么难以查询出完整数据。因此,筛选出hire_date=max(hire_date)的数据为最佳做法,不过需要利用子查询操作,直接写hire_date=max(hire_date)报错。

select * from employees
where hire_date = 
(select max(hire_date) from employees)

Q2 查找员工入职时间排名倒数第三的员工所有信息

数据:employees

同Q1,在不确定同一入职时间有多少员工的情况下,也不能用limit。本题首先要先确定时间倒数第三是哪天,再使用where进行筛选。

select * from employees
where hire_date = (
    select distinct hire_date 
    from employees 
    order by hire_date desc
    limit 2,1)

select distinct对所有的入职日期去重,再进行降序排序,limit 2,1指从第2+1位数1位,即第三位。

Q3 查找当前薪水详情以及部门编号dept_no

数据:薪水表salaries,各个部门的领导表dept_manager

问:找各个部门当前领导的薪水详情以及其对应部门编号dept_no,输出结果以salaries.emp_no升序排序,并且请注意输出结果里面dept_no列是最后一列

本题给了两张表,salaries只有员工编号emp_no和薪水salary,dept_manager中有emp_no和部门编号dept_no,需要使用表连接。

关键:1.题干“dept_manager.dept_no列是最后一列”,所以要把dept_manager连接到salaries上

2.领导表dept_manager中员工编号emp_no与薪水表salaries的emp_no不完全对应,本题要以dept_manager.emp_no为准,因此不可使用左连接,否则会保留非领导员工编号

select s.*, d.dept_no 
from salaries s
join dept_manager d
on s.emp_no = d.emp_no
order by s.emp_no

Q4 查找所有已经分配部门的员工的last_name和first_name以及dept_no

数据:员工表employees和部门表dept_emp

问:查找所有已经分配部门的员工的last_name和first_name以及dept_no,未分配的部门的员工不显示

此题是单纯的表连接,内连接就可以使dept_no为null的不显示

select last_name, first_name, dept_no 
from dept_emp d
join employees e
on d.emp_no = e.emp_no

Q5 查找所有已经分配部门的员工的last_name和first_name以及dept_no(包括暂时没有分配)

同Q4,区别在于需要显示dept_no为null的员工,那么内连接不适用,要以employees.emp_no为准,使用左连接

select last_name, first_name, dept_no 
from employees e
left join dept_emp d
on e.emp_no = d.emp_no 

通过Q4和Q5可以熟悉内连接和左右连接的用法与区别,刚接触很容易搞反,个人的想法是无论left还是right,a join b都会形成先a后b排序的一张表,左连接虽然听起来像是“在左边连接表”,但实际上左右连接是在告诉sql我们要以哪一列为基准去输出连接表,left join则是以a.c=b.c中的a表c列为依据,显示a.c列全部数据,即使其他列有空值,right同理。而内连接为有空值就把整行删除。

Q6 查找薪水记录超过15条的员工号emp_no以及其对应的记录次数t

数据:salaries

查找记录次数使用count函数,先分组,再使用having筛选

select emp_no, count(emp_no) t 
from salaries
group by emp_no
having count(emp_no) > 15

Q7 所有员工当前薪水salary情况

数据:salaries

问:找出所有员工具体的薪水salary情况,对于相同的薪水只显示一次,并按照逆序显示

关键:“只显示一次“意味着使用select distinct

select distinct salary
from salaries
order by salary desc

Q8 获取所有非部门领导的员工emp_no

数据:员工表employees和部门领导表dept_manager

使用not in和子查询,先查询所有领导的emp_no,然后查询不在其中的员工编号即可

select emp_no 
from employees
where emp_no not in (
    select emp_no 
    from dept_manager
    )

Q9 获取所有员工当前的manager

数据:员工表dept_emp和部门经理表dept_manager

问:获取所有的员工和员工对应的经理,如果员工本身是经理的话则不显示

表连接,不显示经理只需使员工表里的编号不等于经理表的编号

select e.emp_no, m.emp_no manager
from dept_emp e
join dept_manager m
on e.dept_no = m.dept_no
where e.emp_no != m.emp_no

Q10 获取每个部门中当前员工薪水最高的相关信息

数据:员工表dept_emp和薪水表salaries

问:获取每个部门中当前员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary,按照部门编号dept_no升序排列

(1)如果不需要给出emp_no字段

select d.dept_no, max(s.salary)
from dept_emp d
join salaries s
on d.emp_no = s.emp_no
group by d.dept_no

(2)原题

不能直接在select处添加emp_no,一个聚合字段(dept_no)对应多个非聚合字段(emp_no),会随机选择非聚合字段中的任何一个。使用窗口函数对每组内薪水进行排名,再查询排名第一的员工信息即可。

select dept_no, emp_no, salary
from (
    select d.dept_no, d.emp_no, s.salary, dense_rank()over(partition by d.dept_no order by s.salary desc) rk
    from dept_emp d
    join salaries s
    on d.emp_no = s.emp_no
    ) f
where f.rk = 1

  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值