牛客网数据库SQL实战剖析(1-10)

1. 查找最晚入职员工的全部信息

CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

解题思路:根据入职时间倒序排序order by ... DESC,而后再取一条记录,就是最晚入职的员工。html

select * from employees 
order by hire_date DESC limit 1;

这样作有一个问题,hire_date是 date 类型,颇有可能多条记录中是同一个时间入职的,因此说时间类型仍是用时间戳比较精切。mysql

来源:https://www.cnblogs.com/Jie-Jack/p/3793304.html

针对这道题目能够使用 MAX() 函数,而后用一个子查询。sql

select * from employees
where hire_date = (select MAX(hire_date) FROM employees);

MAX()先查询出最晚入职的时间,而后再查询出在最晚时间入职的全部员工。yii


2. 查找入职员工时间排名倒数第三的员工全部信息

查找入职员工时间排名倒数第三的员工全部信息函数

CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

解题思路:查询入职时间倒数第三的,要先进行排序,再取三条记录。MySQL中的结果集默认以正序排列,要逆序排列就要使用 DESC,取第三条则是使用limit优化

select * from employees
order by hire_date DESC 
limit 2,1;

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

查找各个部门当前(to_date='9999-01-01')领导当前薪水详情以及其对应部门编号dept_nocode

CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));

CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

解题思路:这是一个等值链接的题目,用员工编号emp_no 作关联便可。htm

select s.*, d.dept_no
from salaries s
join dept_manager d on d.emp_no = s.emp_no
where d.to_date='9999-01-01';

上面的SQL有一个优化的点,就是能够用 s.to_date='9999-01-01' 再进行一次去重锁定。修改以后的 SQL 以下所示:blog

select s.*, d.dept_no
from salaries s
join dept_manager d on d.emp_no = s.emp_no
where d.to_date='9999-01-01'  and s.to_date='9999-01-01';

吐槽:牛客网里,表 dept_manager 用两个字母的别名 dm,居然过不了...排序


4. 查找全部已经分配部门的员工的last_name和first_name以及dept_no

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

CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));

CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

解题思路:这道题开始想到用一个子查询,先查询出全部部门id,做为条件去查询员工表。而后看到还须要查询出部门表里的dept_no ,因此以为用外链接更加合适,用dept_emp 表做为主表进行查询。

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

5. 查找全部员工的last_name和first_name以及对应部门编号dept_no

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

CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));

CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

解题思路:这个和上一题一个意思,只是这题里,没有部门号的也要查询出来,即查询全部员工,以员工表做为主表。

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

6. 查找全部员工入职时候的薪水状况

查找全部员工入职时候的薪水状况,给出emp_no以及salary, 并按照emp_no进行逆序。

CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

解题思路:这道题要考虑到,员工的入职时的薪水状况,即他入职第一个月时的薪水,即employees.​hire_date=salaries.​from_date​​

select e.emp_no, s.salary
from employees e
join salaries s on e.emp_no=s.emp_no and e.hire_date = s.from_date
order by e.emp_no DESC;

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

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

CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`)
);

解题思路:看到这道题第一反应是,这道题也太复杂了。由于薪水涨幅须要比较先后两个月的薪水,若是薪水降低是不能算涨幅的。因此,用解题的思路,我以为这道题不会这么复杂,就大胆假设它默认一直涨薪的。

从应试的角度,我以为它是要考察 group by...having...,也就是先经过 emp_no 进行分组,再过滤分组记录数大于15的记录

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

果真是这样。不用纠结这道题的题意,知道考察点在group by...having...就好了。

MySQL having子句


8. 找出全部员工当前薪水salary状况

找出全部员工当前(to_date='9999-01-01')具体的薪水salary状况,对于相同的薪水只显示一次,并按照逆序显示

CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

解题思路:这道题讲到了,相同的薪水只显示一次,就是让咱们用 DISTINCT 去重。

select DISTINCT salary
from salaries
where to_date='9999-01-01'
order by salary DESC;

9. 获取全部部门当前manager的当前薪水状况,给出dept_no, emp_no以及salary,当前表示to_date='9999-01-01'

获取全部部门当前manager的当前薪水状况,给出dept_no, emp_no以及salary,当前表示to_date='9999-01-01'

CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));

CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

解题思路:这道题先看表结构,emp_no,dept_nodept_manager 表的主键,这就表示一个部门可能有多个领导,而后dept_manager 去关联salaries 表查询工资便可,限制条件是查询当天的工资 s.to_date='9999-01-01';

select d.dept_no, d.emp_no, s.salary
from dept_manager d
join salaries s on d.emp_no = s.emp_no
where s.to_date='9999-01-01';

可是我这样写,居然AC不过,导入数据后发现,查询结果是这样的,意思就是一个部门的一个领导,在同一天会有多份工资??

d001	10002	72527
d001	10002	72527
d001	10002	72527
d001	10002	72527
d001	10002	72527
d001	10002	72527
d004	10004	40054
d004	10004	42283
d004	10004	42542
d004	10004	46065
d004	10004	48271
d004	10004	50594
d004	10004	52119
d004	10004	54693
d004	10004	58326

要再加一个查询条件d.to_date='9999-01-01',看讨论说是表示在职的经理。

select d.dept_no, d.emp_no, s.salary
from dept_manager d
join salaries s on d.emp_no = s.emp_no
where s.to_date='9999-01-01' and d.to_date='9999-01-01';

10. 获取全部非manager的员工emp_no

获取全部非manager的员工emp_no

CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));

CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

解题思路:查找不是 Manager 的员工,即 employees 左链接 dept_manager 以后,没有在 dept_manager 表中查询到记录的员工。因此在关联以后,判断 d.dept_no IS NULL; 就是在 dept_manager 表中没有数据的员工了。

select e.emp_no
from employees e
left join dept_manager d on e.emp_no = d.emp_no
where d.dept_no IS NULL;
相关文章
相关标签/搜索