• 牛客SQL练习题


    之前的综合题有点难度。

    这部分是牛客上面的题目,自我总结:

    1. 简单的一次条件限制的可以轻松写出来;
    2. 需要进行嵌套的子查询,逻辑不清;
    3. 有些函数不太知道。

    https://www.nowcoder.com/ta/sql

    1.查找最晚入职员工的所有信息

    使用子查询

    # 日期相同也无碍
    SELECT * FROM employees
            WHERE hire_date = (SELECT max(hire_date)
    FROM employees)
    # 只能输出一条
    SELECT * FROM employees 
    ORDER BY hire_date DESC LIMIT 1;

    2.查找入职员工时间排名倒数第三的员工所有信息

    先完成子查询,然后根据找到的时间排名,确定该员工所有的信息

    # 若存在同一天多人入职,不好使
    SELECT
    * FROM employees ORDER BY hire_date DESC LIMIT 1 OFFSET 2;
    SELECT * FROM employees 
    WHERE hire_date=(
    SELECT DISTINCT hire_date 
    FROM employees
    ORDER BY hire_date DESC LIMIT 1 OFFSET 2
    );

    3.查找当前薪水详情以及部门编号dept_no

    只使用where

    使用内连接

    使用右连接

    select salaries.emp_no,salary,from_date,salaries.to_date,dept_no 
    from salaries,dept_manager
    where salaries.emp_no = dept_manager.emp_no
    and dept_manager.to_date='9999-01-01'
    and salaries.to_date='9999-01-01'
    order by salaries.emp_no;
    select s.*,d.dept_no
    from salaries as s inner 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';
    select s.*,d.dept_no
    from salaries as s right join dept_manager as d
    on s.emp_no = d.emp_no

    4.查找所有已经分配部门的员工的last_name和first_name以及dept_no

    右连接

    select e.last_name,e.first_name,d.dept_no
    from employees as e right join dept_emp as d
    on e.emp_no = d.emp_no;

    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;

    7.查找薪水记录超过15次的员工号emp_no以及其对应的记录次数t

    count函数,分组group by

    HAVING语句在GROUP BY语句之后;SQL会在分组之后计算HAVING语句

    select emp_no,count(distinct from_date) as t
    from salaries
    group by emp_no
    having t>15;

    8.找出所有员工当前薪水salary情况

    select distinct(salary) 
    from salaries
    order by salary desc;

    10.获取所有非manager的员工emp_no

    not in

    子查询

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

    左连接

    is null

    select e.emp_no
    from employees as e
    left join dept_manager as d
    on e.emp_no=d.emp_no
    where dept_no is null;

    11.获取所有员工当前的manager

    select dept_emp.emp_no, dept_manager.emp_no manager
    from dept_emp ,dept_manager
    where dept_emp.dept_no = dept_manager.dept_no
    and dept_emp.emp_no <> dept_manager.emp_no

    ☆12.获取每个部门中当前员工薪水最高的相关信息(难)

    内连接,外表,内表查询每个部门工资最高的

    外表与内表,固定部门

    select d.dept_no,d.emp_no,s.salary
    from dept_emp as d inner join salaries as s
    on d.emp_no = s.emp_no
    where s.salary in (
    select max(s2.salary)
    from dept_emp as d2
    inner join salaries as s2
    on d2.emp_no = s2.emp_no
    and d2.dept_no = d.dept_no #最高薪水,员工表连接
    )
    order by d.dept_no;

    15.查找employees表emp_no与last_name的员工信息

    select *
    from employees
    where emp_no % 2 = 1 and last_name != 'Mary'
    order by hire_date desc
    select *
    from employees
    where MOD(emp_no, 2)=1 and last_name != 'Mary'
    order by hire_date desc

    16.统计出当前各个title类型对应的员工当前薪水对应的平均工资

    select title,avg(s.salary)
    from titles as t join salaries as s
    on t.emp_no = s.emp_no
    group by title
    order by avg(s.salary)

    17.获取当前薪水第二多的员工的emp_no以及其对应的薪水salary

    子查询

    select emp_no,salary
    from salaries
    where salary=(
        select distinct salary
        from salaries
        order by salary desc
        limit 1,1 # 第二名
    )

    18.获取当前薪水第二多的员工的emp_no以及其对应的薪水salary(不能使用order by)

    先找出去除第一后的最大值,子查询

    去除第一,子查询

    select e.emp_no,salary,last_name,first_name
    from employees as e inner join salaries as s
    on e.emp_no = s.emp_no
    where salary=(
        SELECT max(salary)
        FROM salaries
        WHERE to_date='9999-01-01'
        AND 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, b.dept_name
    FROM employees AS e
    LEFT JOIN (SELECT d.dept_no,d.dept_name,de.emp_no
    FROM departments AS d
    INNER JOIN dept_emp AS de
    ON d.dept_no=de.dept_no
    ) AS b
    ON e.emp_no=b.emp_no;

    21.查找在职员工自入职以来的薪水涨幅情况

    select b.emp_no,(b.salary-a.salary) as growth
    from
    
    (select e.emp_no,s.salary
    from employees as e join salaries as s
    on e.emp_no = s.emp_no
    and e.hire_date = s.from_date) as a #入职时候的工资
    
    inner join
    
    (select e.emp_no,s.salary
    from employees as e join salaries as s
    on e.emp_no = s.emp_no
    where s.to_date = '9999-01-01')as b#离职时候的工资
    
    on a.emp_no=b.emp_no
    order by growth

    22.统计各个部门的工资记录数

    聚合函数group by

    连接

    行数count

    子查询:首先将部门员工关系表与薪水表(有的人不止一条记录)联系起来,每个人属于哪一个部门,几条薪水记录

    与部门表联系起来,配对上部门的名字

    select de.dept_no,dept_name,t.sum
    from departments as de left join
    
    (select s.emp_no,dept_no,count(d.dept_no) as sum
    from dept_emp as d join salaries as s
    on d.emp_no = s.emp_no
    group by dept_no
    ) as t
    
    on de.dept_no = t.dept_no

    23.对所有员工的薪水按照salary降序进行1-N的排名

    窗口函数dense_rank(),1,1,1,2······

    rank(),1,1,1,4······

    row_number(),1,2,3,4······

    over ( ) as XXX

    select emp_no,salary,dense_rank() over (order by salary desc) as paiming
    from salaries
    where to_date='9999-01-01'
    order by paiming asc,emp_no asc

    24.获取所有非manager员工当前的薪水情况

    select t.dept_no,t.emp_no,f.salary
    from 
    (select de.emp_no,de.dept_no
    from dept_emp as de right join dept_manager as dep
    on de.emp_no != dep.emp_no) as t # 非经理的员工
    
    left join
    (select e.emp_no,salary,to_date
    from salaries as s inner join employees as e
    on e.emp_no = s.emp_no
    where s.to_date='9999-01-01') as f
    
    on t.emp_no = f.emp_no

    (up这段有问题,!= 这部分有问题,)

    select t.dept_no,t.emp_no,s.salary
    from 
    (select de.emp_no,de.dept_no
    from dept_emp as de left join dept_manager as dep
    on de.emp_no = dep.emp_no
    where dep.emp_no is null) as t # 非经理的员工
    
    inner join employees e on t.emp_no = e.emp_no #部门员工关系表
    inner join salaries s on t.emp_no = s.emp_no #薪水表
    where s.to_date='9999-01-01'
    select dep.dept_no, t.emp_no, s.salary
    from(
     select e.emp_no
     from employees e
     left join dept_manager ma on e.emp_no = ma.emp_no
     where ma.emp_no is null # 非经理人员的emp_no
    ) t
    inner join dept_emp dep on t.emp_no = dep.emp_no #部门员工关系表
    inner join salaries s on t.emp_no = s.emp_no #薪水表
    where s.to_date='9999-01-01'

    25.获取员工其当前的薪水比其manager当前薪水还高的相关信息

    我的思路:

    • 找出员工薪水
    • 找出经理薪水
    • 通过部门连接员工与经理
    • 筛选工资条件
    select *
    from 
    (select de.emp_no emp_no,de.dept_no
    from dept_emp as de left join dept_manager as dep
    on de.emp_no = dep.emp_no
    where dep.emp_no is null) as t1 # 找出员工
    
    left join
    
    (select de.emp_no manager_no,de.dept_no
    from dept_emp as de left join dept_manager as dep
    on de.emp_no = dep.emp_no
    where dep.emp_no is not null) as t2 # 找出经理
    
    on t1.dept_no=t2.dept_no

    10001|d001|10002|d001

    select DISTINCT emp_no,manager_no,emp_salary,manager_salary
    from
    (select t1.emp_no,t1.dept_no,salary emp_salary from
    (select de.emp_no emp_no,de.dept_no
    from dept_emp as de left join dept_manager as dep
    on de.emp_no = dep.emp_no
    where dep.emp_no is null) as t1 # 找出员工
    inner join salaries as s on t1.emp_no=s.emp_no) m
    
    left join
    
    
    (select t2.manager_no,t2.dept_no,salary manager_salary from
    (select de.emp_no manager_no,de.dept_no
    from dept_emp as de left join dept_manager as dep
    on de.emp_no = dep.emp_no
    where dep.emp_no is not null) as t2# 找出经理
    inner join salaries as s on t2.manager_no=s.emp_no) n
    
    on m.dept_no=n.dept_no
    
    where manager_salary<emp_salary

    https://www.nowcoder.com/practice/f858d74a030e48da8e0f69e21be63bef?tpId=82&tags=&title=&difficulty=0&judgeStatus=0&rp=1

    26.汇总各个部门当前员工的title类型的分配数目

    • 每个员工所在部门+部门名(部门号)
    • 上表和职称表相连(员工号)
    • 可以根据两个条件分组,且有优先顺序
    select *
    from dept_emp
    left join departments on dept_emp.dept_no=departments.dept_no

    10001|d001|1986-06-26|9999-01-01|d001|Marketing
    10002|d001|1996-08-03|9999-01-01|d001|Marketing
    10003|d002|1995-12-03|9999-01-01|d002|Finance

    select dept_no,dept_name,title,count(title) count
    from
    (select dept_emp.dept_no,emp_no,dept_name
    from dept_emp
    left join departments on dept_emp.dept_no=departments.dept_no) as t
    
    join titles on t.emp_no=titles.emp_no
    group by dept_no,title
    order by dept_no

    28.查找描述信息中包含robot的电影对应的分类名称以及电影数目,而且还需要该分类对应电影数量>=5部

    • 满足条件的电影分类有哪些select film_id,category_id,count(film_id) category_num from film_category GROUP BY category_id having count(film_id)>=5
    • 描述中含有robot
    • 电影分类名称以及数目
    select category.name,count(film.film_id)
    from
    (select film_id,category_id,count(film_id) category_num from film_category GROUP BY category_id having count(film_id)>=5) as t,
    film,category,film_category
    where film.description LIKE '%robot%'
    and film.film_id=film_category.film_id and category.category_id=film_category.category_id # 三个表相连 and t.category_id=category.category_id # 满足条件的电影分类
  • 相关阅读:
    java连接常见数据库的连接字符串
    一个用来自动管理大容量表的Sql脚本
    Ibatis2.0使用说明(一)——入门实例篇
    态度决定你的人生高度
    jboss配置入门(二) -JBOSS3.2.3/3.2.6部署及配置修改
    如何在一个工程里面实现不同的功能打入不同的日志文件中【log4net】
    Xsl实践总结(一)
    Xsl实践总结(三)-介绍一款开发XSL不错的IDE(Stylus)
    Xsl实践总结(二)
    教你节省时间 让你个人效率翻三倍
  • 原文地址:https://www.cnblogs.com/Cookie-Jing/p/14902281.html
Copyright © 2020-2023  润新知