牛客SQL二刷(1-6)

写在前面

正式开始牛客61题二刷的工作,计划是一天六道题,十天整理完所有的题解思路~最近状态起起伏伏,课程作业也到了忙碌的阶段,暑期实习也没个着落,但是学习不能停下来。
信息爆炸带来的焦虑几乎人人都有吧,大量的信息带来的peer pressure真的是无法想象。前几天看了Devon学长的公众号,自己还是需要沉下心,磨好刀。
慢慢来比较快嘛。
告诉自己,准备最好的时间是过去,其次就是现在。

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

这道题有两种主要解法,第一种是使用子查询,固定最后一天这个条件,第二种是不用 MAX 用 ORDER BY 和 LIMIT ,但是这种解法受题目限制(最晚入职不一定只有一个员工),这里也就是记录一下。

-- 第一种,子查询
SELECT * 
FROM employees
WHERE hire_date = (SELECT MAX(hire_date) FROM employees)
-- 这里要注意不能写WHERE hire_date = MAX(hire_date)
-- 第二种,LIMIT 语句(这种适用于天数以及员工记录不重复)
SELECT * 
FROM employees
ORDER BY hire_date DESC
LIMIT 0, 1;
-- 其他写法,LIMIT 1 / LIMIT 1 OFFSET 0
-- 第二种的正确写法
SELECT * 
FROM employees 
WHERE hire_date = 
(
SELECT DISTINCT hire_date 
FROM employees 
ORDER BY hire_date DESC 
LIMIT 0, 1
)

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

这一题和第一题类型就是相同的,用 LIMIT 就比较合适。看下面的语句就知道只改动了一个数字。

SELECT * 
FROM employees 
WHERE hire_date = 
(
SELECT DISTINCT hire_date 
FROM employees 
ORDER BY hire_date DESC 
LIMIT 2, 1
)

Trick 1: 要时刻问自己是否所求记录只有一个,以及 SELECT 的时候是否去重的问题,会增加 AC 的几率

3、查找各个部门当前领导当前薪水详情以及其对应部门编号dept_no

这一系列的时间过滤条件当前为 to_date=‘9999-01-01’ ,解题思路主要就是将两表连结起来,然后根据时间过滤即可。但这道题是有点奇怪的,换了表连接的顺序就不能 AC 了(看题解部分说是输出顺序的问题,我感觉照理说应该是一样的呀emmmm……不知道了)。

-- AC 解法
SELECT s.*, dept_no
FROM salaries AS s
INNER JOIN dept_manager AS d
ON d.emp_no = s.emp_no
WHERE d.to_date = '9999-01-01'
AND s.to_date = '9999-01-01'
-- 不能 AC 
SELECT s.*, dept_no
FROM dept_manager AS d
INNER JOIN salaries AS s
ON d.emp_no = s.emp_no
WHERE d.to_date = '9999-01-01'
AND s.to_date = '9999-01-01'

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

这题有两个表,一个员工表,一个部门表,解题思路就是找出所有存在在部门表里的员工。读到题目有两种语句闪现,一个是两个编号相等,一个是用 IN 语句。这里直接写出前一种,比较好理解。

-- 第一种,自然联结
SELECT last_name, first_name, d.dept_no 
FROM employees AS e
INNER JOIN dept_emp AS d
ON e.emp_no = d.emp_no
-- 第二种,左联结(因为 d 表中一定不存在 null 值)
SELECT last_name, first_name, d.dept_no 
FROM dept_emp AS d 
LEFT JOIN employees AS e 
on e.emp_no = d.emp_no

Trick 2: 要注意哪个表会有 null 值,适用什么样的联结比较好

5、查找所有员工的last_name和first_name以及对应部门编号dept_no,也包括展示没有分配具体部门的员工

这题就是对应上面的第四题了,就是直接可以展现所有员工即可。

SELECT last_name, first_name, d.dept_no 
FROM employees AS e
LEFT JOIN dept_emp AS d
ON e.emp_no = d.emp_no

Trick 3:
INNER JOIN 两边表同时有对应的数据,即任何一边缺失数据就不显示。
LEFT JOIN 会读取左边数据表的全部数据,即便右边表无对应数据。
RIGHT JOIN 会读取右边数据表的全部数据,即便左边表无对应数据。

6、查找所有员工入职时候的薪水情况,给出emp_no以及salary, 并按照emp_no进行逆序

这道题的话主要是考察联结条件,应该注意这几点:

  1. 首先是要将编号进行连接,这显而易见
  2. 根据题意注意到是入职的时候,两个表都有时间信息,因此有限制条件 e.hire_date = s.from_date
  3. 最后按照 emp_no 值逆序排列
SELECT e.emp_no, s.salary 
FROM employees AS e
INNER JOIN salaries AS s
ON e.emp_no = s.emp_no AND e.hire_date = s.from_date
ORDER BY e.emp_no DESC

小总结

以上就是今天的 6 道题,虽然不算难但是也可以在一步步的总结中学到很多,大概费时一小时二十分钟,明天继续加油!

你可能感兴趣的:(SQL学习)