11.获取所有员工当前的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
));
/*本题应注意以下三点:
用 INNER JOIN 连接两张表,因为要输出自己的经理,得知自己与经理的部门要相同,
故有限制条件 de.dept_no = dm.dept_no
再用 WHERE 限制当前员工与当前经理的条件,即 dm.to_date 等于 '9999-01-01' 、
de.to_date 等于 '9999-01-01' 、 de.emp_no 不等于 dm.emp_no
为了增强代码可读性,将 dept_emp 用别名 de 代替,dept_manager 用 dm 代替,
最后根据题意将 de.emp_no 用别名 manager_no 代替后输出
*/
select
de.emp_no, dm.emp_no as manager_no
from
dept_emp as de
inner join
dept_manager as dm
on
de.dept_no = dm.dept_no
where
dm.to_date = '9999-01-01'
and
de.to_date = '9999-01-01'
and
de.emp_no <> dm.emp_no
select
de.emp_no emp_no,dm.emp_no manager_no
from
dept_emp e,dept_manager m
where
e.dept_no=m.dept_no
and
e.to_date='9999-01-01'
and
e.to_date=m.to_date
and
e.emp_no!=m.emp_no;
12.获取所有部门中当前员工薪水最高的相关信息,给出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 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、先用INNER JOIN连接两张表,限制条件是两张表的emp_no相同,即d.emp_no = s.emp_no;
2、选取每个员工当前的工资水平,用d.to_date = '9999-01-01' AND s.to_date = '9999-01-01'
作条件限制,因为此表中每条最新记录的 to_date 都用 9999-01-01 表示;
3、用GROUP BY d.dept_no将每个部门分为一组,用MAX()函数选取每组中工资最高者;
4、将salaries用s代替,dept_emp用d代替,最后将MAX(s.salary)用salary代替后输出。*/
select
d.dept_no, s.emp_no, max(a.salary) as salary
from
salaries s
inner join
dept_emp d
on
s.emp_no = d.emp_no
where
s.to_date = '9999-01-01'
and
d.to_date = '9999-01-01'
group by
d.dept_no;
select
d.dept_no,d.emp_no,max(s.salary) salary
from
dept_emp d,salaries s
where
d.to_date='9999-01-01'
and
s.to_date='9999-01-01'
and
d.emp_no=s.emp_no
group by
d.dept_no;
13.从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);
SELECT
title, COUNT(title) AS t
FROM
titles
GROUP BY
title
HAVING
t >= 2;
14.查找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
));
输出示例:
select * from employees
where emp_no % 2 = 1
and last_name <> 'Mary'
order by hire_date desc;
select * from employees
where emp_no % 2 = 1
and last_name != 'Mary'
order by hire_date desc;
15.统计出当前各个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);
select t.title,avg(s.salary) as avg
from titles as t
inner join salaries as s
on s.emp_no=t.emp_no
and t.to_date='9999-01-01'
and s.to_date='9999-01-01'
group by t.title;
16.获取当前(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
));
输出描述:
select emp_no,salary
from salaries
where to_date='9999-01-01'
order by salary desc
limit 1,1;
17.查找当前薪水(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 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
));
输出描述:
/*本题做法很多,主要思想为多层SELECT嵌套与MAX()函数结合
先利用MAX()函数找出salaries中当前薪水最高者,即SELECT MAX(salary) FROM salaries WHERE to_date = '9999-01-01'
再利用INNER JOIN连接employees与salaries表,限定条件为【同一员工】e.emp_no = s.emp_no、【当前】s.to_date = '9999-01-01'与【非薪水最高】s.salary NOT IN (SELECT MAX(salary) FROM salaries WHERE to_date = '9999-01-01')
在以上限制条件下找薪水最高者,即为所有员工薪水的次高者*/
select e.emp_no,max(s.salary) AS salary,e.last_name,e.first_name
from employees AS e inner join salaries AS s
on e.emp_no=s.emp_no
where to_date='9999-01-01'
and salary not in
(select max(salary) from salaries);
select s.emp_no,max(s.salary) as salary,e.last_name,e.first_name
from salaries s,employees e
where s.emp_no=e.emp_no
and s.to_date='9999-01-01'
and s.salary < (select max(salary) from salaries);
18.查找所有员工的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
));
输出描述:
ELECT e.last_name, e.first_name, dp.dept_name
FROM employees AS e
LEFT JOIN dept_emp AS d
ON e.emp_no = d.emp_no
LEFT JOIN departments AS dp
ON d.dept_no = dp.dept_no;
/*本题思路为运用两次LEFT JOIN连接嵌套
1、第一次LEFT JOIN连接employees表与dept_emp表,得
到所有员工的last_name和first_name以及对应的dept_no,
也包括暂时没有分配部门的员工
2、第二次LEFT JOIN连接上表与departments表,即连接
dept_no与dept_name得到所有员工的last_name和
first_name以及对应的dept_name,也包括暂时没有分配
部门的员工*/
SELECT em.last_name, em.first_name, dp.dept_name
FROM (employees AS em
LEFT JOIN dept_emp AS de
ON em.emp_no = de.emp_no)
LEFT JOIN
departments AS dp ON de.dept_no = dp.dept_no;
19.查找员工编号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
));
输出描述:
/*本题严谨的思路如下:
1、先分别找到emp_no=10001的员工的第一次工资记录与最后
一次工资记录
2、再将最后一次工资记录减去第一次工资记录得到入职以来
salary的涨幅,最后用别名growth代替*/
SELECT (
(SELECT salary FROM salaries WHERE emp_no = 10001
ORDER BY to_date DESC LIMIT 1) -
(SELECT salary FROM salaries WHERE emp_no = 10001
ORDER BY to_date ASC LIMIT 1)
) AS growth
/*本题的另一种解法也能通过测试,但实际上不严谨,只有在员工
最后一条工资记录为最大值时成立,如果最后一次的工资调整为
降薪,则此思路通不过。具体思路如下:
直接找到emp_no=10001的员工的工资记录,将其最大工资
减去最小工资得到涨幅*/
SELECT (MAX(salary)-MIN(salary)) AS growth
FROM salaries WHERE emp_no = '10001'
20.查找所有员工自入职以来的薪水涨幅情况,给出员工编号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左连接employees与salaries,
建立两张表,分别存放员工当前工资(sCurrent)与员工入职时的工
资(sStart),再用INNER JOIN连接sCurrent与sStart,最后限
定在同一员工下用当前工资减去入职工资。
方法一:内层用LEFT JOIN,外层用INNER JOIN(内层也可以改用
INNER JOIN)*/
SELECT sCurrent.emp_no, (sCurrent.salary-sStart.salary) AS growth
FROM(
SELECT s.emp_no, s.salary FROM employees e
LEFT JOIN salaries s ON e.emp_no = s.emp_no
WHERE s.to_date = '9999-01-01'
) AS sCurrent
INNER JOIN
(
SELECT s.emp_no, s.salary FROM employees e
LEFT JOIN salaries s ON e.emp_no = s.emp_no
WHERE s.from_date = e.hire_date
) AS sStart
ON sCurrent.emp_no = sStart.emp_no
ORDER BY growth;
/*方法二:内外都层用FROM并列查询*/
SELECT sCurrent.emp_no, (sCurrent.salary-sStart.salary) AS growth
FROM(
SELECT s.emp_no, s.salary FROM employees e, salaries s
WHERE e.emp_no = s.emp_no AND s.to_date = '9999-01-01'
)
AS sCurrent,
(
SELECT s.emp_no, s.salary FROM employees e, salaries s
WHERE e.emp_no = s.emp_no AND s.from_date = e.hire_date
)
AS sStart
WHERE sCurrent.emp_no = sStart.emp_no
ORDER BY growth;