在牛客上看到sql练习题,之前对于多表join类的操作不够熟悉,刚好练习一下
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
));
1 | select * from employees order by hire_date desc limit 1 |
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
));
1 | select * from employees order by hire_date desc limit 2,1 |
limit m,n 表示从m开始,取n个数
3. 查找各个部门当前(to_date=’9999-01-01’)领导当前薪水详情以及其对应部门编号dept_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 TABLEsalaries
(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
));
1 | select s.*, d.dept_no from salaries as s, dept_manager as d where s.to_date='9999-01-01' and d.to_date='9999-01-01' and s.emp_no=d.emp_no |
也可以用join来实现
1 | select s.*, d.dept_no from salaries as s join dept_manager as d on s.emp_no=d.emp_no where s.to_date='9999-01-01' and d.to_date='9999-01-01' |
4. 查找所有已经分配部门的员工的last_name和first_name
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
));
1 | select e.last_name, e.first_name, d.dept_no from employees as e, dept_emp as d where e.emp_no=d.emp_no |
5. 查找所有员工的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
));
1 | select e.last_name, e.first_name, d.dept_no from employees as e left join dept_emp as d on e.emp_no=d.emp_no |
6. 查找薪水涨幅超过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
));
1 | select emp_no, count(1) as t from salaries group by emp_no having t>15 |
这是查出数量大于15条的记录,其实这道题的题意是涨薪15次,应该用join来做
1 | select a.emp_no, count(1) as t from salaries as a left join salaries as b on a.emp_no=b.emp_no and a.to_date=b.from_date group by a.emp_no having t>15 |
7. 获取所有部门当前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
));
1 | select d.dept_no, d.emp_no, s.salary |
8. 获取所有非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
));
方法1:not in
1 | select emp_no from employees where emp_no not in (select emp_no from dept_manager) |
方法2:left join is null
1 | select e.emp_no from employees as e left join |
9. 获取所有员工当前的manager,如果当前的manager是自己的话结果不显示,当前表示to_date=’9999-01-01’。
结果第一列给出当前员工的emp_no,第二列给出其manager对应的manager_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
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
));
1 | select e.emp_no, m.emp_no from dept_emp as e left join |
10. 获取所有部门中当前员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary
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 TABLEsalaries
(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
));
1 | select d.dept_no, s.emp_no, max(s.salary) as salary from |
11. 从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t。
CREATE TABLE IF NOT EXISTS “titles” (
emp_no
int(11) NOT NULL,title
varchar(50) NOT NULL,from_date
date NOT NULL,to_date
date DEFAULT NULL);
1 | select title, count(1) as t from titles group by title having t>=2 |
12. 从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t。
注意对于重复的emp_no的title进行忽略。
CREATE TABLE IF NOT EXISTS
titles
(emp_no
int(11) NOT NULL,title
varchar(50) NOT NULL,from_date
date NOT NULL,to_date
date DEFAULT NULL);
1 | select title, count(distinct emp_no) as t from titles group by title having t>=2 |
13. 查找employees表所有emp_no为奇数,且last_name不为Mary的员工信息,并按照hire_date逆序排列
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
));
1 | select emp_no,birth_date, first_name, last_name, gender, hire_date from employees |
14.统计出当前各个title类型对应的员工当前(to_date=’9999-01-01’)薪水对应的平均工资。结果给出title以及平均工资avg。
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
));CREATE TABLE IF NOT EXISTS “titles” (
emp_no
int(11) NOT NULL,title
varchar(50) NOT NULL,from_date
date NOT NULL,to_date
date DEFAULT NULL);
1 | select t.title, avg(s.salary) as avg from titles as t inner join salaries as s on t.emp_no=s.emp_no |
####15. 获取当前(to_date=’9999-01-01’)薪水第二多的员工的emp_no以及其对应的薪水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
));
要去掉工资相同的情况
1 | select emp_no, salary from salaries |
16. 查找当前薪水(to_date=’9999-01-01’)排名第二多的员工编号emp_no、薪水salary、last_name以及first_name,不准使用order by
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 TABLEsalaries
(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
));
用两遍max来代理order by limit 1,1
1 | select e.emp_no, max(s.salary) as salary, e.last_name, e.first_name |
####17. 查找所有员工的last_name和first_name以及对应的dept_name,也包括暂时没有分配部门的员工
CREATE TABLE
departments
(dept_no
char(4) NOT NULL,dept_name
varchar(40) NOT NULL,
PRIMARY KEY (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
));
三个表两次级联
1 | select e.last_name, e.first_name, dp.dept_name |
18. 查找员工编号emp_no为10001其自入职以来的薪水salary涨幅值growth
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
));
两次查找,一次以to_date正向排序,一次逆向排序
1 | select |
19. 查找所有员工自入职以来的薪水涨幅情况,给出员工编号emp_no以及其对应的薪水涨幅growth,并按照growth进行升序
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
));
方法一:用两次left join,加一次inner join
1 | SELECT sCurrent.emp_no, (sCurrent.salary-sStart.salary) AS growth |
方法二:用多次select
1 | SELECT sCurrent.emp_no, (sCurrent.salary-sStart.salary) AS growth |