MySQL(八)—— 联合查询和子查询

本文深入讲解SQL中的联合查询、子查询、OrderBy使用等高级技巧,包括各种子查询分类及其应用场景,帮助读者掌握复杂数据检索的方法。

目录

联合查询

基本语法

意义

Order by使用

子查询

子查询分类

标量子查询

列子查询

行子查询

表子查询

Exists子查询


联合查询

联合查询: 将多次查询(多条select语句), 在记录上进行拼接(字段不会增加)

基本语法

多条select语句构成: 每一条select语句获取的字段数必须严格一致(但是字段类型无关)

Select 语句1

Union [union选项]

Select语句2...

Union选项: 与select选项一样有两个

All: 保留所有(不管重复)

Distinct: 去重(整个重复): 默认的

-- 联合查询 默认去重
select * from my_class
union -- 默认去重
select * from my_class;

-- 不去重
select * from my_class
union all -- 不去重
select * from my_class;

联合查询只要求字段一样, 跟数据类型无关

select id,c_name,room from my_class
union all -- 不去重
select name,number,id from my_student;

意义

联合查询的意义分为两种:

1. 查询同一张表,但是需求不同: 如查询学生信息, 男生身高升序, 女生身高降序.

2. 多表查询: 多张表的结构是完全一样的,保存的数据(结构)也是一样的.

 

Order by使用

在联合查询中: order by不能直接使用,需要对查询语句使用括号才行

-- 需求: 男生升序,女生降序(年龄)
(select * from my_student where sex = '男' order by age asc)
union 
(select * from my_student where sex = '女' order by age desc);

若要orderby生效: 必须搭配limit: limit使用限定的最大数即可.

-- 需求: 男生升序,女生降序(年龄)
(select * from my_student where sex = '男' order by age asc limit 9999999)
union 
(select * from my_student where sex = '女' order by age desc limit 9999999);

 

子查询

子查询: sub query, 查询是在某个查询结果之上进行的.(一条select语句内部包含了另外一条select语句).

子查询分类

子查询有两种分类方式: 按位置分类; 按结果分类

按位置分类: 子查询(select语句)在外部查询(select语句)中出现的位置

From子查询: 子查询跟在from之后

Where子查询: 子查询出现where条件中

Exists子查询: 子查询出现在exists里面

按结果分类: 根据子查询得到的数据进行分类(理论上讲任何一个查询得到的结果都可以理解为二维表)

标量子查询: 子查询得到的结果是一行一列

列子查询: 子查询得到的结果是一列多行

行子查询: 子查询得到的结果是多列一行(多行多列)

上面几个出现的位置都是在where之后

表子查询: 子查询得到的结果是多行多列(出现的位置是在from之后)

标量子查询

需求: 知道班级名字为PHP0710,想获取该班的所有学生.

  1. 确定数据源: 获取所有的学生

Select * from my_student where c_id = ?;

  1. 获取班级ID: 可以通过班级名字确定

Select id from my_class where c_name = ‘PHP0710’; -- id一定只有一个值(一行一列)

标量子查询实现

-- 标量子查询
select * from my_student where c_id = (select id from my_class where c_name = 'PHP0710');

列子查询

需求: 查询所有在读班级的学生(班级表中存在的班级)

  1. 确定数据源: 学生

Select * from my_student where c_id in (?);

  1. 确定有效班级的id: 所有班级id

Select id from my_class;

列子查询

-- 列子查询
select * from my_student where c_id in(select id from my_class);

列子查询返回的结果会比较: 一列多行, 需要使用in作为条件匹配: 其实在mysql中有还有几个类似的条件: all, some, any

Any  ====  in; -- 其中一个即可

Any ====== some; -- any跟some是一样

all    ==== 为全部

肯定结果

-- any,some,all
select * from my_student where c_id =any(select id from my_class);
select * from my_student where c_id =some(select id from my_class);
select * from my_student where c_id =all(select id from my_class);

否定结果

select * from my_student where c_id !=any(select id from my_class); -- 所有结果(null除外)
select * from my_student where c_id !=some(select id from my_class); -- 所有结果(null除外)
select * from my_student where c_id !=all(select id from my_class); -- 2(null除外)

行子查询

行子查询: 返回的结果可以是多行多列(一行多列)

需求: 要求查询整个学生中,年龄最大且身高是最高的学生.

  1. 确定数据源

Select * from my_student where age = ? And height = ?;

  1. 确定最大的年龄和最高的身高;

Select max(age),max(height) from my_student;

行子查询: 需要构造行元素: 行元素由多个字段构成

-- 行子查询
select * from my_student where 
-- (age,height)称之为行元素
(age,height) = (select max(age),max(height) from my_student);

 

表子查询

表子查询: 子查询返回的结果是多行多列的二维表: 子查询返回的结果是当做二维表来使用

需求: 找出每一个班最高的一个学生.

  1. 确定数据源: 先将学生按照身高进行降序排序

Select * from my_student order by height desc;

  1. 从每个班选出第一个学生

Select * from my_student group by c_id; -- 每个班选出第一个学生

表子查询: from子查询: 得到的结果作为from的数据源

-- 表子查询
select * from (select * from my_student order by height desc) as student group by c_id;

Exists子查询

Exists: 是否存在的意思, exists子查询就是用来判断某些条件是否满足(跨表), exists是接在where之后: exists返回的结果只有0和1.

需求: 查询所有的学生: 前提条件是班级存在

  1. 确定数据源

Select * from my_student where ?;

  1. 确定条件是否满足

Exists(Select * from my_class); -- 是否成立

Exists子查询

-- exists子查询
select * from my_student where 
exists(select * from my_class where id = 1);

select * from my_student where 
exists(select * from my_class where id = 2);

 

### 关于 MySQL 子查询与 UNION 联合查询 #### 子查询使用方法 子查询是指在一个 SQL 查询内部嵌套另一个查询。它可以用于从其他表中获取数据并将其作为条件的一部分来过滤结果。以下是子查询一个典型示例: ```sql SELECT e.ename, (SELECT d.dname FROM dept d WHERE e.deptno = d.deptno) AS dname FROM emp e; ``` 上述代码展示了如何通过子查询动态地为员工表中的每一行附加部门名称[^2]。 --- #### UNION 的基本概念 UNION 是一种用于合并两个或多个 SELECT 语句的结果集的操作符。它会自动去除重复的记录,而如果希望保留所有记录,则可以使用 UNION ALL。下面是一个简单的例子: ```sql SELECT class_id, name, age FROM `学生表` UNION SELECT id, title, NULL FROM `班级表`; ``` 此代码片段将来自 `学生表` `班级表` 的字段组合在一起,并确保最终结果集中没有重复项[^1]。 --- #### 综合应用:子查询与 UNION 结合 当需要同时利用子查询 UNION 来处理复杂的数据需求时,可以通过以下方式实现: 假设我们有一个场景——要展示学生的姓名以及他们所属的班级名;如果没有对应班级信息,则显示为空字符串。我们可以这样编写 SQL: ```sql -- 部分一:基于子查询提取学生成绩及其对应班级名 SELECT s.name AS student_name, COALESCE((SELECT c.class_name FROM classes c WHERE s.class_id = c.id), '') AS class_name FROM students s UNION -- 部分二:单独列出未分配任何学生班级 SELECT '', c.class_name FROM classes c WHERE NOT EXISTS ( SELECT 1 FROM students s WHERE s.class_id = c.id); ``` 这里的第一部分使用子查询来匹配每个学生与其所在的班级名字,第二部分则找出那些没有任何关联学生的孤立班级[^3]。 --- #### 注意事项 - **去重行为**:默认情况下,UNION 会对结果进行去重操作。如果不需要这种功能,可以选择 UNION ALL。 - **字段数量一致性类型兼容性**:参与 UNION 的各个 SELECT 语句必须具有相同数量的列,并且相应位置上的列应具备可比较的数据类型。 --- 问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值