[MySQL]子查询(三)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: [MySQL]子查询(三)

6.2.3 其他题目

查询平均工资最低的部门id

MySQL中聚合函数不能嵌套使用

方式一:

# 查询平均工资最低的部门id
SELECT department_id, AVG(salary) "avg_sal"
FROM employees
GROUP BY department_id
HAVING avg_sal = (
    # 查询出所有部门中的最低工资
    SELECT MIN(avg_sal)
    # 在from中使用子查询,需要为子查询取别名
    FROM (
             # 查询所有部门的平均工资
             SELECT AVG(salary) "avg_sal"
             FROM employees
             GROUP BY department_id
         ) t_dep_avg_sal
);

方式二:

# 查询平均工资最低的部门id
SELECT department_id, AVG(salary) "avg_sal"
FROM employees
GROUP BY department_id
# 筛选出平均工资小于等于  所有部门平均工资  的部门
# 即筛选出平均工资最低的部门id
HAVING avg_sal <= ALL (
    # 查询所有部门的平均工资
    SELECT AVG(salary) "avg_sal"
    FROM employees
    GROUP BY department_id
);

6.3 空值问题

注意内查询返回的null值

SELECT last_name
FROM employees
WHERE employee_id NOT IN (
    SELECT manager_id
    FROM employees
);

SELECT manager_id
FROM employees;

由于子查询中有null值的返回,null参与外层查询的NOT IN运算,会返回null,所以每条记录与null运算都返回null,所以查询不出记录。

排除空值,即可返回正确结果。

# 查询不为管理者的员工的姓名
SELECT last_name
FROM employees
WHERE employee_id NOT IN (
    SELECT manager_id
    FROM employees
    WHERE manager_id IS NOT NULL
);

7. 相关子查询

如果子查询的执行依赖于外部查询,通常情况下都是因为子查询中的表用到了外部的表,并进行了条件关联,因此每执行一次外部查询,子查询都要重新计算一次,这样的子查询就称之为 关联子查询 。

7.1 相关子查询执行流程

相关子查询按照一行接一行的顺序执行,主查询的每一行都会执行一次子查询。

7.2 相关子查询示例

查询员工中工资大于本部门平均工资的员工的last_name,salary和其department_id

方法一:

# 查询员工中工资大于本部门平均工资的员工的last_name,salary和其department_id
SELECT last_name,
       salary,
       department_id
FROM employees e1
WHERE salary > (
    SELECT AVG(salary)
    FROM employees e2
    WHERE e2.department_id = e1.department_id
    );

方法二:

不相关子查询

# 查询员工中工资大于本部门平均工资的员工的last_name,salary和其department_id
SELECT e1.last_name,
       e1.salary,
       e1.department_id
FROM employees e1,
     (
         SELECT e2.department_id,
                AVG(e2.salary) "avg_sal"
         FROM employees e2
         GROUP BY e2.department_id
     ) dep_avg_sal
WHERE e1.department_id = dep_avg_sal.department_id AND
      e1.salary > dep_avg_sal.avg_sal;

7.3 在ORDER BY 中使用相关子查询

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

# 查询员工的id,salary,按照department_name 排序
SELECT employee_id,
       salary
FROM employees e
ORDER BY (
             SELECT department_name
             FROM departments d
             WHERE d.department_id = e.department_id
         );

7.4 在WHERE中使用相关子查询

若employees表中employee_id与job_history表中employee_id相同的数目不小于2,输出这些相同id的员工的employee_id,last_name和其job_id

# 若employees表中employee_id  与job_history表中employee_id相同  的数目不小于2,
# 输出这些相同id的员工的employee_id,last_name和其job_id
SELECT employee_id,
       last_name,
       job_id
FROM employees e
WHERE 2 <= (
          SELECT COUNT(*)
          FROM job_history j
          WHERE e.employee_id = j.employee_id
      );

7.5 EXISTS 与 NOT EXISTS关键字

关联子查询通常也会和 EXISTS 操作符一起来使用,用来检查在子查询中是否存在满足条件的行。

  • 如果在子查询中不存在满足条件的行:
  • 条件返回 FALSE
  • 继续在子查询中查找
  • 如果在子查询中存在满足条件的行:
  • 不在子查询中继续查找
  • 条件返回 TRUE

NOT EXISTS关键字表示如果不存在某种条件,则返回TRUE,否则返回FALSE。

7.5.1 题目1

查询公司管理者的employee_id,last_name,job_id,department_id信息

# 方式一:自连接
SELECT DISTINCT m.employee_id,
                m.last_name,
                m.job_id,
                m.department_id
FROM employees e,
     employees m
WHERE e.manager_id = m.employee_id;

# 方式二:子查询
SELECT employee_id,
       last_name,
       job_id,
       department_id
FROM employees
WHERE employee_id IN (
    SELECT DISTINCT manager_id
    FROM employees
    WHERE manager_id IS NOT NULL
    );

# 方式三:使用EXISTS
SELECT employee_id,
       last_name,
       job_id,
       department_id
FROM employees e1
# 判断子查询中是否有记录存在
# 外层查询的当前行与子查询中使用的表二进行一一对比
# 当外层的employee_id = 表二的manager_id 即子查询中存在记录
# 此时不在进行查询返回true
# 否则继续查询直到查询完整个表,返回false
WHERE EXISTS(
    SELECT *
    FROM employees e2
    WHERE e1.employee_id = e2.manager_id
          );

7.5.2 题目2

查询departments表中,不存在于employees表中的部门的department_id和department_name

# 查询departments表中,不存在于employees表中的部门的department_id和department_name
SELECT department_id,
       department_name
FROM departments d
# 每行数据进入子查询与子查询中的表的每行进行匹配
# 当当前行与子查询表中的每行都匹配不成功时,即子查询没有一行数据
# NOT EXISTS返回true
WHERE NOT EXISTS(
    SELECT *
    FROM employees e
    WHERE e.department_id = d.department_id
    );

8. 子查询可以声明的位置

在SELECT中,除了GROUP BY 和 LIMIT之外,其他位置都可以声明子查询!

SELECT的完整结构

#sql99语法:
SELECT ...., ...., ....(存在聚合函数)
FROM ... 
(LEFT / RIGHT)JOIN ....ON 多表的连接条件 
(LEFT / RIGHT)JOIN ... ON ....
WHERE 不包含聚合函数的过滤条件
GROUP BY ..., ....
HAVING 包含聚合函数的过滤条件
ORDER BY ...., ...(ASC / DESC )
LIMIT ..., ....


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
SQL 关系型数据库 MySQL
mysql子查询、聚合函数
mysql子查询、聚合函数
|
1月前
|
关系型数据库 MySQL
Mysql基础第十七天,使用子查询
Mysql基础第十七天,使用子查询
20 0
|
1月前
|
SQL 关系型数据库 MySQL
MySQL子查询篇(精选20道子查询练习题)-2
MySQL子查询篇(精选20道子查询练习题)
41 0
|
1月前
|
SQL 关系型数据库 MySQL
MySQL子查询篇(精选20道子查询练习题)-1
MySQL子查询篇(精选20道子查询练习题)
53 0
|
1天前
|
SQL 关系型数据库 MySQL
MySQL数据库子查询练习——EXISTS(存在)
MySQL数据库子查询练习——EXISTS(存在)
9 1
|
1天前
|
SQL 关系型数据库 MySQL
MySQL数据库子查询——in多个数据查询的示例
MySQL数据库子查询——in多个数据查询的示例
8 1
|
1天前
|
SQL 关系型数据库 MySQL
MySQL数据库子查询练习——单个数据的子查询
MySQL数据库子查询练习——单个数据的子查询
7 1
|
1天前
|
SQL 关系型数据库 MySQL
MySQL数据库子查询练习——DDL与DML语句(包括引入视频)
MySQL数据库子查询练习——DDL与DML语句(包括引入视频)
5 1
|
9天前
|
SQL 关系型数据库 MySQL
MySQL数据库——多表查询(3)-自连接、联合查询、子查询
MySQL数据库——多表查询(3)-自连接、联合查询、子查询
13 1
|
11天前
|
关系型数据库 MySQL
11. Mysql 子查询
11. Mysql 子查询