美文网首页
牛客网sql实战(一)

牛客网sql实战(一)

作者: MisterDo | 来源:发表于2019-11-16 20:38 被阅读0次

    1.查找最晚入职员工的所有信息
    注意:同一天入职的可能有多个人
    法一:利用max函数找到最大的hire_date对应的员工信息(最优)

    法二:利用order by 和 limit找到最大的一个hire_date对应的员工信息

    2.查找入职员工时间排名倒数第三的员工所有信息
    注意:同一天入职的可能有多个人
    法一:利用order by 和 limit找到倒数第三的hire_date对应的员工信息

    法二:同一天入职的如果有多个人,那么倒数第三的员工并不是按照时间日期排的,更严谨的做法,是利用子查询结合distincnt 和order by 和 limit找到入职日期倒数第三的hire_date对应的员工信息

    3.查找各个部门当前(to_date='9999-01-01')领导当前薪水详情以及其对应部门编号
    以salary为主表,进行内连接查找
    4.查找所有已经分配部门的员工的last_name和first_name
    以dept_emp为主表,进行内连接查找
    5.查找所有员工的last_name和first_name以及对应部门编号dept_no,也包括展示没有分配具体部门的员工
    外连接

    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.查找所有员工入职时候的薪水情况,给出emp_no以及salary, 并按照emp_no进行逆序
    注意内连接与where并列查询的区别:
    内连接是取左右两张表的交集形成一个新表,用FROM并列两张表后仍然还是两张表。如果还要对新表进行操作则要用内连接。从效率上看应该FROM并列查询比较快,因为不用形成新表。本题从效果上看两个方法没区别。

    7.查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t
    解决本题的关键在于要记得,sql语句的执行顺序,先group by emp_no,按员工编号进行分组,然后执行select中的count(emp_no) 最后执行having中的过滤条件

    一个sql查询语句的主要组成部分为
    select --- from --- where --- group by --- having --- order by --- limit --- ;
    执行顺序:

    1. from
    2. where
    3. group by
    4. select
    5. having
    6. ordre by
    7. limit
    select emp_no,count(emp_no) as t from salaries group by emp_no having t>15;
    

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

    在单表的时候使用distinct,多表的时候使用group by,虽然一般使用group by ,但还是要知道distinct的用法

    单表用distinct:

    select distinct salary from salaries where to_date='9999-01-01'
    order by salary desc;
    

    多表用group by:

    select salary from salaries where to_date='9999-01-01'
    group by salary order by salary desc;
    

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

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

    10.获取所有非manager的员工emp_no
    方法一:

    select emp_no from employees where emp_no not in 
    (select emp_no from dept_manager)
    

    方法二:

    select emp_no from (select * from employees as e left join dept_manager as d
    on e.emp_no=d.emp_no) where dept_no is NUll
    

    11.获取所有员工当前的manager,如果当前的manager是自己的话结果不显示,当前表示to_date='9999-01-01'。
    结果第一列给出当前员工的emp_no,第二列给出其manager对应的manager_no。

    select e.emp_no,m.emp_no from dept_emp as e 
    inner join dept_manager as m 
    on e.dept_no=m.dept_no
    and e.emp_no<>m.emp_no
    and e.to_date='9999-01-01' 
    and m.to_date='9999-01-01';
    

    12.获取所有部门中当前员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary
    1.先内连接两张表
    2.按dept_no进行分组
    3.找出组内最大薪水的成员

    select d.dept_no,d.emp_no,max(s.salary) from dept_emp as d inner join salaries as s 
    on d.emp_no=s.emp_no where d.to_date="9999-01-01" and s.to_date="9999-01-01"
    group by d.dept_no
    

    13.从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t

    select title,count(title) as t from titles group by title having t>=2;
    

    14.从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t。
    注意对于重复的emp_no进行忽略。

    select title ,count(distinct emp_no) as t from titles
    group by title having t>=2;
    

    15.查找employees表所有emp_no为奇数,且last_name不为Mary的员工信息,并按照hire_date逆序排列

    select * from employees where emp_no%2=1 
    and  last_name<>"Mary" 
    order by hire_date desc;
    

    16.统计出当前各个title类型对应的员工当前(to_date='9999-01-01')薪水对应的平均工资。结果给出title以及平均工资avg

    select t.title,avg(s.salary) from titles as t 
    inner join salaries as s on t.emp_no=s.emp_no
    where t.to_date="9999-01-01" and s.to_date="9999-01-01"
    group by t.title;
    

    17.获取当前(to_date='9999-01-01')薪水第二多的员工的emp_no以及其对应的薪水salary

    select emp_no,salary from salaries order by salary desc limit 1,1;
    

    改进版:针对于薪水相同的员工,上述做法无法真正得到按薪水排第二的员工信息

    select emp_no,salary from salaries  where to_date='9999-01-01'  
    and salary =(select distinct salary from salaries order by salary desc limit 1,1);
    

    18.查找当前薪水(to_date='9999-01-01')排名第二多的员工编号emp_no、薪水salary、last_name以及first_name,不准使用order by
    从薪水不是第一的里面找最大值

    select e.emp_no,max(s.salary),e.last_name,e.first_name
    from employees as e inner join salaries as s
    on e.emp_no=s.emp_no where s.to_date='9999-01-01' and 
    s.salary<>(select max(salary) from salaries where to_date='9999-01-01')
    

    19.查找所有员工的last_name和first_name以及对应的dept_name,也包括暂时没有分配部门的员工

    select e.last_name,e.first_name,d.dept_name
    from employees as e left join 
    (select * from dept_emp inner join departments on dept_emp.dept_no=departments.dept_no) as d
    on e.emp_no=d.emp_no
    

    20.查找员工编号emp_no为10001其自入职以来的薪水salary涨幅值growth

    select (max(salary)-min(salary)) as growth from salaries where emp_no='10001'
    

    更严谨的做法:

    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
    

    21.查找所有员工自入职以来的薪水涨幅情况,给出员工编号emp_no以及其对应的薪水涨幅growth,并按照growth进行升序

    select a.emp_no,(b.salary-c.salary) as growth
    from employees as a 
    inner join salaries as b on a.emp_no=b.emp_no and b.to_date='9999-01-01'
    inner join salaries as c on a.emp_no=c.emp_no and c.from_date=a.hire_date
    order by growth
    

    22.统计各个部门对应员工涨幅的次数总和,给出部门编码dept_no、部门名称dept_name以及次数sum

    • 将员工与其薪水内连接成一张表,该表为一个员工有多种薪水
    • 将部门表与上表内连接,按部门编号分组
    • 每个部门中,多种薪水的员工对应多个部门编号,count部门编号即为该部门内所有员工的涨薪次数之和
    select d.dept_no,d.dept_name,count(d.dept_no) as sum from departments as d inner join 
    (select * from dept_emp as a inner join salaries as b 
    on a.emp_no=b.emp_no) as c on d.dept_no=c.dept_no
    group by d.dept_no
    

    相关文章

      网友评论

          本文标题:牛客网sql实战(一)

          本文链接:https://www.haomeiwen.com/subject/khlyictx.html