牛客SQL二刷(7-12)

7、查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t

这道题其实是有难点的,因为要求第二次薪水比第一次薪水高才能算是涨幅,而 AC 答案却没有考虑这一点,所以牛客也是奇奇怪怪的…,主要目标还是要解决一下如何展现这个涨幅。
一般这种要找前一个和后一个关系的比如两个连座啊,连续几天这种,都会用到一个小 trick 就是一张表用两次。这里的联结条件需要注意:
a.emp_no = b.emp_no AND a.to_date = b.from_date
然后我们只需要用 WHERE 表明涨即可了。

SELECT a.emp_no, COUNT(a.emp_no) AS t 
FROM salaries AS a 
INNER JOIN salaries AS b
ON a.emp_no = b.emp_no AND a.to_date = b.from_date 
-- 上一次的结束是下一次的开始
WHERE a.salary < b.salary
GROUP BY a.emp_no
HAVING t > 15

8、找出所有员工当前薪水salary情况

本题还是比较常规的,注意其他的小条件:对于相同的薪水只显示一次,并按照逆序显示。用好 DISTINCT 和 ORDER BY 就行了。

SELECT DISTINCT salary
FROM salaries
WHERE to_date = '9999-01-01'
ORDER BY salary DESC

在看题解的时候看到另一种解法,并且有人说明,
对于distinct与group by的使用:

  1. 当对系统的性能高并数据量大时使用group by
  2. 当对系统的性能不高时使用数据量少时两者皆可
  3. 尽量使用group by
SELECT salary 
FROM salaries
WHERE to_date='9999-01-01'
GROUP BY salary
ORDER BY salary DESC;

但其实我自己有一点没想明白的就是这个员工是铁定不会重复的是么。。大概是的(噢我看到了emp_no是主键,打扰了打扰了)

9、获取所有部门当前manager的当前薪水情况

这道题比上道题就是多个联结过程,因为求的是 manager 的薪水情况,依然要注意到两个当前的过滤条件。

SELECT d.dept_no, d.emp_no, s.salary
FROM dept_manager AS d
INNER JOIN salaries AS s
ON d.emp_no = s.emp_no 
AND d.to_date = '9999-01-01'
AND s.to_date = '9999-01-01'
ORDER BY d.emp_no
SELECT d.dept_no, d.emp_no, s.salary 
FROM salaries AS s INNER JOIN dept_manager AS d 
ON d.emp_no = s.emp_no
AND d.to_date = '9999-01-01'
AND s.to_date = '9999-01-01'

这里是给了顺序互换的两种联结方式哈,首先思路一定是比较清晰的,但是 OJ 系统也是非常奇怪,讨论区大佬的思路是这样子
原因分析可能如下:连接后按照前面的第一个 KEY 值排序,若 salaries 在前,则按照 s.emp_no 排序(因为限制条件为 d.emp_no = s.emp_no,所以对 s.emp_no 排序就是对d.emp_no 排序),输出跟参考答案一致,没问题;若 dept_manager 在前,则按照 d.dept_no排序,此时与参考答案不同,所以需要在末尾手动用 ORDER BY 对d.emp_no进行排序。
这里就是记录一下,以防之后不能 AC 时可以朝这个思路去排查。

10、获取所有非manager的员工emp_no

这道题呢就讲到这个 NOT IN 了。我在讨论区也看到了别的解法。

-- 方法一 NOT IN 
SELECT emp_no
FROM employees
WHERE emp_no NOT IN 
(
SELECT emp_no
FROM dept_manager
)
-- 方法二 左联结找 NULL 值
SELECT e.emp_no 
FROM employees AS e
LEFT JOIN dept_manager AS d
ON e.emp_no = d.emp_no
WHERE dept_no IS NULL

也就是说按照员工编号进行两个表的联结,而且是以员工表为主,那么一定存在非 manager 的员工,他的 dept_no 是 NULL 值,用过滤条件即可。

11、获取所有员工当前的manager

如果当前的manager是自己的话结果不显示。
这道题的话,要点还是要一一对应,以及如何表现这个员工所对应的 manager (还不能表示 manager 本人),可以反过来进行推理,如果本人就是 manager ,那么这两个字段值是相等的,那么我们就找不相等的就好了。其实我们发现很多 SQL 语句的书写关键就是在于一个逻辑的转化。

SELECT de.emp_no, dm.emp_no AS manager_no 
FROM dept_emp AS de 
INNER JOIN dept_manager AS dm
ON de.dept_no = dm.dept_no 
WHERE dm.to_date = '9999-01-01' 
AND de.to_date = '9999-01-01' 
AND de.emp_no <> dm.emp_no -- 用!= 也可以

12、获取所有部门中当前员工薪水最高的相关信息

这道题的话首先是每个部门而不是所有部门的,所以要用 GROUP BY ,注意也是两个当前,一个是当前雇佣的员工,一个是当前的薪水(因为我们总要在一个固定的时间节点上进行比较嘛,一般来说是当前时间的),如何用MAX 就好了,应该是没有什么难度的。

SELECT d.dept_no, d.emp_no, MAX(s.salary)
FROM dept_emp AS d
INNER JOIN salaries AS s 
ON d.emp_no = s.emp_no 
AND d.to_date = s.to_date
WHERE d.to_date = '9999-01-01'
GROUP BY d.dept_no
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值