牛客网sql题详解11-20

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));
输出描述:
牛客网sql题详解11-20_第1张图片

/*此题思路如下:
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);
牛客网sql题详解11-20_第2张图片

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));
输出示例:
牛客网sql题详解11-20_第3张图片

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);
牛客网sql题详解11-20_第4张图片

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));
输出描述:
牛客网sql题详解11-20_第5张图片

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));
牛客网sql题详解11-20_第6张图片

/*本题思路是先分别用两次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;

你可能感兴趣的:(牛客网sql题详解11-20)