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
针对这道题目能够使用 MAX()
函数,而后用一个子查询。sql
select * from employees where hire_date = (select MAX(hire_date) FROM employees);
MAX()
先查询出最晚入职的时间,而后再查询出在最晚时间入职的全部员工。yii
查找入职员工时间排名倒数第三的员工全部信息函数
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;
查找各个部门当前(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,居然过不了...排序
查找全部已经分配部门的员工的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;
查找全部员工的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;
查找全部员工入职时候的薪水状况,给出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;
查找薪水涨幅超过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...
就好了。
找出全部员工当前(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;
获取全部部门当前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_no
是dept_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';
获取全部非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;