MySQL数据库(22):子查询 sub query

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: MySQL数据库(22):子查询 sub query

子查询 sub query

1、基本概念

1.1、子查询

嵌套查询下层的程序模块,当一个查询是另一个查询的条件时,称之为子查询

一条select语句中,嵌入了另一条select语句

1.2、主查询

主要的查询对象,第一条select语句,确定所获取的数据目标(数据源)

1.3、子查询和主查询的关系

  1. 子查询是嵌入到主查询中的
  2. 子查询辅助主查询,要么作为条件,要么作为数据源
  3. 子查询可以独立存在,是一条完整的select语句

1.4、子查询的分类

1、按功能分

  1. 标量子查询:子查询返回的结果是一个数据(一行一列)
  2. 列子查询:返回一列(一列多行)
  3. 行子查询:返回一行(一行多列)
  4. 表子查询:返回多行多列
  5. exists子查询 返回1或者0(类似布尔操作)

2、按位置分

  1. where子查询
  2. from子查询

2、标量子查询

查询结果是一个数据(一行一列)

2.1、基本语法

-- 子查询得到的结果只有一个值
select * from 数据源 where 条件判断 =/<> (select 字段名 form 数据源 where 条件判断);
• 1
• 2

2.2、示例

-- 知道学生的id,查询所在班级名字
-- 主查询:班级,子查询:班级id
mysql> select * from my_student;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  4 | 张飞   |        2 |   21 |      1 |
|  5 | 关羽   |        1 |   22 |      2 |
|  6 | 曹操   |        1 |   20 |   NULL |
+----+--------+----------+------+--------+
mysql> select * from my_class;
+----+--------+
| id | name   |
+----+--------+
|  1 | 一班   |
|  3 | 三班   |
|  2 | 二班   |
+----+--------+
select class_id from my_student where id = 1;
+----------+
| class_id |
+----------+
|        1 |
+----------+
select * from my_class where id = (
    select class_id from my_student where id = 1
);
+----+--------+
| id | name   |
+----+--------+
|  1 | 一班   |
+----+--------+

3、列子查询

列子查询得到的结果是一列数据,一列多行

3.1、基本语法

主查询 where 条件 in (列子查询)
• 1

3.2、示例

-- 获取有学生的班级名字
-- 1、找到学生表中的所有班级id
-- 2、找出班级表中对应的名字
select distinct(class_id) from my_student;
+----------+
| class_id |
+----------+
|        1 |
|        2 |
+----------+
select name from my_class where id in (
    select distinct(class_id) from my_student
);
+--------+
| name   |
+--------+
| 一班   |
| 二班   |
+--------+

4、行子查询

行子查询返回的结果是一行多列

  • 字段元素:一个字段对应的值
  • 行元素:多个字段合起来作为一个元素参与运算

4.1、基本语法

主查询 where 条件 [(构造一个行元素)] = (行子查询);

4.2、示例

获取班级年龄最大,且班级号最大的学生
1、求年龄最大
2、求班级号最大
3、求出学生
-- 错误示例
select * from my_student having age = max(age) and class_id = max(class_id);
-- 1、having在group by之后,代表group by执行了一次,聚合函数使用
-- 2、group by 一旦执行,结果就是只返回一行记录,第一行 
select max(age), max(class_id) from my_student;
+----------+---------------+
| max(age) | max(class_id) |
+----------+---------------+
|       22 |             2 |
+----------+---------------+
select * from my_student where (age, class_id) = (
    select max(age), max(class_id) from my_student
);
Empty set (0.01 sec)
select * from my_student where (age, class_id) = (
    select max(age), min(class_id) from my_student
);
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  5 | 关羽   |        1 |   22 |      2 |
+----+--------+----------+------+--------+

总结:

标量子查询、列子查询、行子查询都属于where子查询

5、表子查询

表子查询返回结果是多行多列,与行子查询相似

行子查询需要行元素,表子查询没有

  • 行子查询用于where条件判断,属于where子查询
  • 表子查询用于from数据源,属于from子查询

5.1、基本语法

select 字段表 from (表子查询) as 别名 [where] [group by] [having] [order by] [limit]
• 1

5.2、示例

获取每个班级年龄最大的学生
-- 错误示例
select * from my_student group by class_id having age = max(age);
将每个班年龄最大的学生排在最前面 order by
针对结果进行group by 保留每组第一条数据
-- 
select * from (
    select * from my_student order by age desc
) as t group by t.class_id;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  3 | 王五   |        2 |   20 |      2 |
+----+--------+----------+------+--------+

6、exists子查询

返回结果只有0或者1,1代表成立,0代表不成立

6.1、基本语法

where exists (查询语句)
-- 永远为真
where 1;

6.2、示例

-- 查询有学生的所有班级
select * from my_class as c where exists (
    select id from my_student as s where s.class_id = c.id
);
+----+--------+
| id | name   |
+----+--------+
|  1 | 一班   |
|  2 | 二班   |
+----+--------+

7、子查询中的特定关键字

mysql> select * from my_student;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  4 | 张飞   |        2 |   21 |      1 |
|  5 | 关羽   |        1 |   22 |      2 |
|  6 | 曹操   |        1 |   20 |   NULL |
+----+--------+----------+------+--------+
mysql> select id from my_class;
+----+
| id |
+----+
|  1 |
|  3 |
|  2 |
+----+

7.1、in

主查询 where 条件 in (列子查询)
select * from my_student where class_id in (select id from my_class);
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  4 | 张飞   |        2 |   21 |      1 |
|  5 | 关羽   |        1 |   22 |      2 |
|  6 | 曹操   |        1 |   20 |   NULL |
+----+--------+----------+------+--------+

7.2、any

-- 查询结果中有任意一个匹配即可,等价于in
主查询 where 条件 any (列子查询)
select * from my_student where class_id = any (select id from my_class);
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  4 | 张飞   |        2 |   21 |      1 |
|  5 | 关羽   |        1 |   22 |      2 |
|  6 | 曹操   |        1 |   20 |   NULL |
+----+--------+----------+------+--------+
-- 不等于任意一个
主查询 where 条件 any <> (列子查询)
select * from my_student where class_id <> any (select id from my_class);
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  4 | 张飞   |        2 |   21 |      1 |
|  5 | 关羽   |        1 |   22 |      2 |
|  6 | 曹操   |        1 |   20 |   NULL |
+----+--------+----------+------+--------+

7.3、some

与any完全一样

7.4、all

-- 等于其中所有
=all(列子查询)
select * from my_student where class_id = all (select id from my_class);
Empty set (0.00 sec)
select * from my_class where id = all (select class_id from my_student);
Empty set (0.00 sec)
-- 不等于其中所有
<>all(列子查询)
select * from my_student where class_id <> all (select id from my_class);
Empty set (0.00 sec)
select * from my_class where id <> all (select class_id from my_student);
+----+--------+
| id | name   |
+----+--------+
|  3 | 三班   |
+----+--------+

7.5、值为null

如果值为null,不参与匹配

mysql> select * from my_student;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  4 | 张飞   |        2 |   21 |      1 |
|  5 | 关羽   |     NULL |   22 |      2 |
|  6 | 曹操   |        1 |   20 |   NULL |
+----+--------+----------+------+--------+
mysql> select * from my_student where class_id = any (select id from my_class);
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  4 | 张飞   |        2 |   21 |      1 |
|  6 | 曹操   |        1 |   20 |   NULL |
+----+--------+----------+------+--------+
mysql> select * from my_student where class_id <> any (select id from my_class);
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  4 | 张飞   |        2 |   21 |      1 |
|  6 | 曹操   |        1 |   20 |   NULL |
+----+--------+----------+------+--------+
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3天前
|
存储 关系型数据库 MySQL
10个案例告诉你mysql不使用子查询的原因
大家好,我是V哥。上周与朋友讨论数据库子查询问题,深受启发。为此,我整理了10个案例,详细说明如何通过优化子查询提升MySQL性能。主要问题包括性能瓶颈、索引失效、查询优化器复杂度及数据传输开销等。解决方案涵盖使用EXISTS、JOIN、IN操作符、窗口函数、临时表及索引优化等。希望通过这些案例,帮助大家在实际开发中选择更高效的查询方式,提升系统性能。关注V哥,一起探讨技术,欢迎点赞支持!
|
4月前
|
SQL 关系型数据库 MySQL
在 MySQL 中使用子查询
【8月更文挑战第12天】
248 0
在 MySQL 中使用子查询
|
6月前
|
SQL 关系型数据库 MySQL
MySQL数据库子查询练习——EXISTS(存在)
MySQL数据库子查询练习——EXISTS(存在)
85 1
|
6月前
|
SQL 关系型数据库 MySQL
MySQL数据库子查询——in多个数据查询的示例
MySQL数据库子查询——in多个数据查询的示例
42 1
|
6月前
|
关系型数据库 分布式数据库 数据库
数据库内核那些事|PolarDB IMCI让你和复杂低效的子查询说拜拜
PolarDB IMCI(In-Memory Column Index)确实是数据库领域的一项重要技术,特别是当它面对复杂和低效的子查询时,表现尤为出色。以下是关于PolarDB IMCI如何助力解决
|
3月前
|
SQL 缓存 关系型数据库
MySQL高级篇——关联查询和子查询优化
左外连接:优先右表创建索引,连接字段类型要一致、内连接:驱动表由数据量和索引决定、 join语句原理、子查询优化:拆开查询或优化成连接查询
|
4月前
|
SQL 数据库 数据安全/隐私保护
什么是数据库子查询?
【8月更文挑战第2天】
176 14
什么是数据库子查询?
|
5月前
|
存储 缓存 监控
如何优化数据库子查询?
【7月更文挑战第22天】如何优化数据库子查询?
112 15
|
4月前
|
SQL 数据处理 数据库
SQL进阶之路:深入解析数据更新与删除技巧——掌握批量操作、条件筛选、子查询和事务处理,提升数据库维护效率与准确性
【8月更文挑战第31天】在数据库管理和应用开发中,数据的更新和删除至关重要,直接影响数据准确性、一致性和性能。本文通过具体案例,深入解析SQL中的高级更新(UPDATE)和删除(DELETE)技巧,包括批量更新、基于条件的删除以及使用子查询和事务处理复杂场景等,帮助读者提升数据处理能力。掌握这些技巧能够有效提高数据库性能并确保数据一致性。
101 0
|
5月前
|
关系型数据库 MySQL 数据库
MySQL—子查询
MySQL—子查询