数据库实战每日6题(1 ~ 6)
- 查找最晚入职员工的所有信息
- 查找入职员工时间排名倒数第三的员工所有信息
- 查找当前薪水详情以及部门编号dept_no
- 查找所有已经分配部门的员工的last_name和first_name
- 查找所有员工的last_name和first_name以及对应部门编号dept_no
- 查找所有员工入职时候的薪水情况
查找最晚入职员工的所有信息
题目链接
题目
解析
- 思路一: 使用嵌套查询(子查询),内层查询先查询出来表中的最大的hire_date,外层再查一次;
- 思路二: 按照hire_date降序排列,然后使用limit关键字取出第一项即可;
select * from employees where hire_date = (select max(hire_date) from employees);
select * from employees order by hire_date desc limit 0,1;
select * from employees order by hire_date desc limit 1;
注意limit关键字的使用:
- LIMIT m,n : 表示从第m+1条开始,取n条数据;
- LIMIT n : 表示从第0条开始,取n条数据,是limit(0,n)的缩写。
查找入职员工时间排名倒数第三的员工所有信息
题目链接
题目
解析
- 思路一: 直接使用desc hire_date 降序排列,然后使用limit来选出倒数第三个;
- 思路二: 上面的思路如果hire_date 有重复的话,就不能选到真正的名词,所以可以使用distinct关键字选出不重复的hire_date,然后排序,这个查询嵌套在内查询中;
-- 简单的想法
select * from employees order by hire_date desc limit 2,1;
-- 严密的思路
select * from employees
where hire_date =
-- 先筛选出不重复的 hrie_date 然后再排序,然后再选择倒数第三的
(select distinct hire_date from employees order by hire_date desc limit 2,1);
查找当前薪水详情以及部门编号dept_no
题目链接
题目
解析
- 思路一: 使用多表查询,其中使用where 条件来连接两个表;
- 思路二: 使用inner join来连接查询,on 后面带上条件;
注意这里使用部门表作为主表不能通过,可能因为两个表的逻辑关系,题目要求是薪水情况以及部门编号;
以下三种方式都可以:
-- 不使用join
select tb_s.*,tb_d.dept_no
from salaries as tb_s,dept_manager as tb_d
where tb_s.emp_no = tb_d.emp_no
and tb_s.to_date = '9999-01-01'
and tb_d.to_date = '9999-01-01';
-- 使用join
select tb_s.*,tb_d.dept_no
from salaries as tb_s inner join dept_manager as tb_d
on tb_s.emp_no = tb_d.emp_no
and tb_s.to_date = '9999-01-01'
and tb_d.to_date = '9999-01-01';
select tb_s.*,tb_d.dept_no
from salaries as tb_s inner join dept_manager as tb_d
on tb_s.emp_no = tb_d.emp_no
where tb_s.to_date = '9999-01-01' and tb_d.to_date = '9999-01-01';
查找所有已经分配部门的员工的last_name和first_name
题目链接
题目
解析
- 思路一: 使用等值连接,可以使用where 连接,也可以使用join;
- 思路二: 直接使用自然连接 natural join;
注意几种连接的区别:
-- 等值连接 where
select tb_e.last_name,tb_e.first_name,tb_d.dept_no
from employees as tb_e,dept_emp as tb_d
where tb_e.emp_no = tb_d.emp_no;
-- 等值连接 join 连接查询
select tb_e.last_name,tb_e.first_name,tb_d.dept_no
from employees as tb_e inner join dept_emp as tb_d
on tb_e.emp_no = tb_d.emp_no;
-- 使用自然连接 (两个表的同一列属性的值相同)
select tb_e.last_name,tb_e.first_name,tb_d.dept_no
from employees tb_e natural join dept_emp tb_d;
查找所有员工的last_name和first_name以及对应部门编号dept_no
题目连接
题目
解析
- 这里使用左连接查询,左边的全,右边的为null的就显示null;
注意JOIN的区别:
- INNER JOIN 两边表同时有对应的数据,即任何一边缺失数据就不显示;
- LEFT JOIN 会读取左边数据表的全部数据,即便右边表无对应数据;
- RIGHT JOIN 会读取右边数据表的全部数据,即便左边表无对应数据;
注意on与where区别,两个表连接时用on,在使用LEFT JOIN时,on和where条件的区别如下:
- on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。
- where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有LEFT JOIN的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。
更多关于ON 和 WHERE的知识看这篇博客。
select tb_e.last_name,tb_e.first_name,tb_d.dept_no
from employees tb_e left join dept_emp as tb_d
on tb_e.emp_no = tb_d.emp_no;
查找所有员工入职时候的薪水情况
题目链接
题目
解析
- 测试数据中,salaries.emp_no不唯一(因为号码为emp_no的员工会有多次涨薪的可能,所以在salaries中对应的记录不止一条),employees.emp_no唯一,即salaries的数据会多于employees,因此需先找到tb_e.emp_no在tb_s表中对应的记录salaries.emp_no,则有限制条件tb_e.emp_no = tb_s.emp_no;
- 根据题意注意到salaries.from_date 和employees.hire_date的值应该要相等,因此有限制条件 tb_e.hire_date = tb_s.from_date;
select tb_e.emp_no,tb_s.salary
from employees as tb_e inner join salaries as tb_s
on tb_e.emp_no = tb_s.emp_no
and tb_e.hire_date = tb_s.from_date -- 注意这个员工入职时候的薪水
order by tb_e.emp_no desc;