【MySQL】详解20道例题带你学习子查询,偷偷做卷王(二)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 【MySQL】详解20道例题带你学习子查询,偷偷做卷王(二)

例题3

查询与141号员工的manager_id和department_id相同的其他员工的employee_id,

manager_id,department_id
SELECT employee_id,manager_id,department_id
FROM employees
WHERE manager_id = (
      SELECT manager_id
      FROM employees
      WHERE employee_id = 141
     )
AND department_id = (
      SELECT department_id
      FROM employees
      WHERE employee_id = 141
     )
AND employee_id <> 141;
#解题思路:分别查询141号员工的manager_id和department_id,并且最终要出去141号员工本身


例题4

查询最低工资大于50号部门最低工资的部门id和其最低工资


SELECT department_id , MIN(salary)
FROM employees
WHERE department_id IS NOT NULL
GROUP BY department_id
HAVING MIN(salary) > 
    (SELECT MIN(salary) FROM employees 
      WHERE department_id = 50);
#解题思路:因为有聚合函数,所以要考虑分组查询;按照department_id分组后查询其最低工资大于50号部门的最低工资,这里用到了having中的子查询


例题5

显式员工的employee_id,last_name和location。其中,若员工department_id与location_id为1800的department_id相同,则location为’Canada’,其余则为’USA’,这里用到了流程控制,小伙伴们要是流程控制不熟悉的话,可以看看我写的流程控制总结:MySQL流程控制大总结
SELECT employee_id, last_name,
       (CASE department_id
        WHEN
             (SELECT department_id FROM departments
       WHERE location_id = 1800)           
        THEN 'Canada' 
        ELSE 'USA' 
        END) AS location
FROM   employees;
#这里用到了case中嵌套子查询


2、多行子查询例题

例题6

查询与141号或174号员工的manager_id和department_id相同的其他员工的employee_id,manager_id,department_id

employee_id,manager_id,department_id
SELECT employee_id,manager_id,department_id
FROM employees
WHERE manager_id IN(
  SELECT manager_id FROM employees WHERE employee_id IN (141,171)
)
AND department_id IN (
  SELECT department_id FROM employees WHERE employee_id IN (141,174)
)
AND employee_id <> 141 AND 174;
#这里与例题3类似,只是返回的结果是多个值,属于多行子查询



例题7

返回其它job_id中比job_id为‘IT_PROG’部门任一工资低的员工的员工号、姓名、

job_id 以及salary
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE job_id <> 'IT_PROG'
AND salary < ANY (
  SELECT salary
  FROM employees
  WHERE job_id = 'IT_PROG'
  );
#这里重点是使用关键字any,意思就是满足其中一个条件即可


例题8

查询平均工资最低的部门id (题目虽短,但是有一定的难度)


#方式1:
SELECT department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary) = (
    SELECT MIN(avg_sal)
    FROM (
    SELECT AVG(salary) avg_sal
    FROM employees
    GROUP BY department_id
    ) dept_avg_sal
    )
#解题思路:1、先根据部门id分组查询各个部门的平均工资
   2、然后把 1 中的查询结果当成一个新的表,并且要给该表取表名(dept_avg_sal)
   3、然后从新表中查询最低的平均工资
   4、1 2 3 步一起组成一个内查询,实现题目要求
#方式2:
SELECT department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary) <= ALL (
    SELECT AVG(salary) avg_sal
    FROM employees
    GROUP BY department_id
)
#对比方式一,这个就比较好理解了,要查询的平均工资只要不大于所有部门的平均工资就可以了



3、相关子查询例题

例题9

查询员工的id,salary,按照department_name 排序


SELECT employee_id,salary
FROM employees e
ORDER BY (
   SELECT department_name
   FROM departments d
   WHERE e.`department_id` = d.`department_id`
  );
#解题思路:因为员工表中没有部门名,但是可以根据e.`department_id` = d.`department_id`
#这一条件来进行关联,即内查询用到了主查询,这就是相关子查询


例题10

在employees中增加一个department_name字段,数据为员工对应的部门名称


UPDATE employees e
SET department_name =  (SELECT department_name 
                        FROM   departments d
                        WHERE  e.department_id = d.department_id);
#这里用到了相关更新的操作,使用相关子查询依据一个表中的数据更新另一个表的数据,道理是一样的


例题11

删除表employees中,其与emp_history表皆有的数据


DELETE FROM employees e
WHERE employee_id in  
           (SELECT employee_id
            FROM   emp_history 
            WHERE  employee_id = e.employee_id);
#这里用到了相关删除的操作,使用相关子查询依据一个表中的数据删除另一个表的数据


4、综合例题

例题12

查询和姓名中包含字母u的员工在相同部门的员工的员工号和姓名
SELECT employee_id,last_name
FROM employees 
WHERE department_id IN (
    SELECT DISTINCT department_id
    FROM employees
    WHERE last_name LIKE '%u%'
    );
#解题思路:还是老方法,先查询姓名中包含字母U的员工部门号,注意用到了关键字IN


例题13

查询工资最低的员工信息: last_name, salary


SELECT last_name,salary
FROM employees
WHERE salary = (
  SELECT MIN(salary)
  FROM employees
  );
#这里用到了聚合函数


例题14

查询出公司中所有 manager 的详细信息


SELECT employee_id,last_name,job_id,department_id
FROM employees e1
WHERE EXISTS (
        SELECT *
        FROM employees e2
        WHERE e1.`employee_id` = e2.`manager_id`
      );
#这里使用了EXISTS关键字,当e1.`employee_id` = e2.`manager_id`成立,内查询为true时,就继续执行


例题15

查询部门的部门号,其中不包括job_id是"ST_CLERK"的部门号


SELECT department_id
FROM departments d
WHERE NOT EXISTS (
  SELECT *
  FROM employees e
  WHERE d.`department_id` = e.`department_id`
  AND e.`job_id` = 'ST_CLERK'
  );
#这里用到了关键字 NOT EXISTS,与EXISTS 相反,只有为false时,才继续执行


例题16

选择所有没有管理者的员工的last_name


SELECT last_name
FROM employees emp
WHERE NOT EXISTS (
  SELECT *
  FROM employees mgr
  WHERE emp.`manager_id` = mgr.`employee_id`
  );


例题17

查询员工号、姓名、雇用时间、工资,其中员工的管理者为 ‘De Haan’


SELECT employee_id,last_name,hire_date,salary
FROM employees e1
WHERE EXISTS (
  SELECT *
  FROM employees e2
  WHERE e1.`manager_id` = e2.`employee_id`
  AND e2.last_name = 'De Haan'
  );


例题18

查询各部门中工资比本部门平均工资高的员工的员工号, 姓名和工资


SELECT last_name,salary,department_id
FROM employees e1
WHERE salary > (
  SELECT AVG(salary)
  FROM employees e2
  WHERE department_id = e1.`department_id`
  );
#这里考察相关子查询的使用


例题19

查询每个部门下的部门人数大于 5 的部门名称(相关子查询)


SELECT department_name
FROM departments d
WHERE 5 < (
    SELECT COUNT(*)
    FROM employees e
    WHERE d.department_id = e.`department_id`
   );


例题20

查询工资最低的员工信息: last_name, salary


SELECT *
FROM departments
WHERE department_id = (
    SELECT department_id
    FROM employees
    GROUP BY department_id
    HAVING AVG(salary ) =(
      SELECT AVG(salary) avg_sal
      FROM employees
      GROUP BY department_id
      ORDER BY avg_sal ASC
      LIMIT 1  
      )
    );
#这里用到了LIMIT关键字,
# 1 分组排序后用limit获取最低的工资
# 2 再根据部门id分组后筛选平均工资等于 1 中的结果
# 3 根据 2 获取的查询结果,实现题目要求
# 难度有点高,实现方式不止一种。


总结

可以说,子查询是SQL查询语句难度到达了顶峰,与前面学习到的排序、分页、分组查询等等相结合。我应该没事巩固例题,加强训练,相信自己一定可以搞明白子查询,最后再画出脉络图!

image.png

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
20小时前
|
关系型数据库 MySQL 数据库管理
【MySQL进阶之路 | 基础篇】子查询之二(不相关子查询与相关子查询)
【MySQL进阶之路 | 基础篇】子查询之二(不相关子查询与相关子查询)
|
20小时前
|
SQL 关系型数据库 MySQL
【MySQL进阶之路 | 基础篇】子查询之一(单行子查询, 多行子查询)
【MySQL进阶之路 | 基础篇】子查询之一(单行子查询, 多行子查询)
|
8天前
|
存储 关系型数据库 MySQL
学习MySQL(5.7)第二战:四大引擎、账号管理以及建库(干货满满)
学习MySQL(5.7)第二战:四大引擎、账号管理以及建库(干货满满)
|
8天前
|
SQL 数据库
mysql-相关子查询
该任务是找出未选修任何课程的学生学号和姓名。通过在教学数据库中使用SQL子查询,先获取选修了课程的学生学号集合,然后在外层查询中找出不在这个集合中的学生信息。代码实现为:`select sno, sname from student where sno not in (select distinct sno from score);`
20 0
|
8天前
|
数据库
mysql-相关子查询
任务是找出选修了课程004的学生姓名和所在系。在teachingdb数据库中,使用子查询和EXISTS关键字来实现。代码示例:`select sname, sdept from student a where exists (select * from score b where a.sno=b.sno and b.cno=004);`
13 0
|
8天前
|
关系型数据库 MySQL 数据库
MySQL -相关子查询
该任务是数据库查询,目标是找出所有选修了&quot;刘东明&quot;所选全部课程的学生学号。需运用子查询和NOT EXISTS运算符。代码首先选择学生表中名字不是&#39;刘东明&#39;的学生,然后检查他们是否存在与&#39;刘东明&#39;相同的所有课程记录。
18 0
|
8天前
|
SQL 数据库
mysql-相关子查询
在教学数据库teachingdb中,使用子查询和NOT EXISTS运算符找出选修了所有课程的学生学号。代码如下: ```sql SELECT sno FROM student a WHERE NOT EXISTS (SELECT cno FROM course b WHERE NOT EXISTS (SELECT * FROM score WHERE sno=a.sno AND cno=b.cno)); ``` 这段SQL语句查找的是没有匹配未选修课程记录的学生学号,即这些学生选修了所有课程。
12 0
|
8天前
|
SQL 数据可视化 关系型数据库
【MySQL-11】多表查询全解-【多表关系/内外自连接/子查询/多表查询案例链接】(可cv代码&案例演示)
【MySQL-11】多表查询全解-【多表关系/内外自连接/子查询/多表查询案例链接】(可cv代码&案例演示)
|
8天前
|
SQL 关系型数据库 MySQL
【MySQL】DQL-排序查询-语法&注意事项&可cv例题语句
【MySQL】DQL-排序查询-语法&注意事项&可cv例题语句
|
8天前
|
SQL 关系型数据库 MySQL
【MySQL】DQL-排序查询-语法&排序方式&注意事项&可cv例题语句
【MySQL】DQL-排序查询-语法&排序方式&注意事项&可cv例题语句