


专栏:MySQL数据库成长记
个人主页:手握风云
目录
[1.1. 应用场景](#1.1. 应用场景)
[1.2. 示例](#1.2. 示例)
[1.3. 表连接练习](#1.3. 表连接练习)
[2.1. 语法](#2.1. 语法)
[2.2. 单行子查询](#2.2. 单行子查询)
[2.3. 多行子查询](#2.3. 多行子查询)
[2.4. 多列子查询](#2.4. 多列子查询)
[2.5. 在from子句中使用子查询](#2.5. 在from子句中使用子查询)
[3.1. 创建新表并初始化数据](#3.1. 创建新表并初始化数据)
[3.2. Union](#3.2. Union)
[3.3. Union all](#3.3. Union all)
[4.1. 语法](#4.1. 语法)
[4.2. 示例](#4.2. 示例)
一、自链接
1.1. 应用场景
自连接是⾃⼰与⾃⼰取笛卡尔积,可以把行转化成列,在查询的时候可以使用where条件对结果进行过滤,或者说实现行与行之间的比较。在做表连接时为表起不同的别名。
1.2. 示例
- 显示所有"MySQL"成绩比"JAVA"成绩高的成绩信息
sql
-- 显示MySQL成绩比Java成绩高
select s1.score as 'Java成绩',s2.score as 'MySQL成绩' from score s1, score s2 , course c1, course c2
where
s1.student_id = s2.student_id
and
c1.`name` = 'Java'and c2.`name` = 'MySQL'
and
s1.course_id = c1.id and s2.course_id = c2.id
and
s2.score > s1.score;

1.3. 表连接练习
- 显示所有"MySQL"成绩比"JAVA"成绩高的学生信息和班级以及成绩信息
sql
-- 显示所有"MySQL"成绩比"JAVA"成绩高的学生信息和班级以及成绩信息
select stu.*, c.`name`,s1.score as 'Java成绩',s2.score as 'MySQL成绩' from
student stu,
class c,
score s1,
score s2,
course c1,
course c2
where
stu.id = s1.student_id -- 学生表和分数表之间建立关系
AND
s1.student_id = s2.student_id -- 两个分数表之间建立s
AND
stu.class_id = c.id -- 学生表和班级表之间建立关联关系
AND
c1.`name` = 'Java'
AND
c2.`name` = 'MySQL'
AND
s1.course_id = c1.id
AND
s2.course_id = c2.id
AND
s2.score > s1.score; -- 进行分数的比较

二、子查询
子查询是把一个SELECT语句的结果当作另一个SELECT语句的条件,也叫嵌套查询。子查询可以无限嵌套,在工作中要注意嵌套的深度。
2.1. 语法
sql
select * from table1 where col_name1 { = | IN } (
select col_name1 from table2 where col_name2 {= | IN} [(
select ......)
]
)
2.2. 单行子查询
- 示例:查询与"Paul"同学的同班同学
步骤:1.查出不想毕业同学的class_id;2.根据class_id查出学生表中学生信息。
sql
SELECT class_id FROM student WHERE `name` = 'Paul';
SELECT * FROM student WHERE class_id = 1;
sql
SELECT class_id FROM student WHERE `name` = 'Paul';
SELECT * FROM student WHERE class_id = 2;

2.3. 多行子查询
嵌套的查询中返回多行数据,使用[NOT] IN关键字。
- 示例:查询MySQL或Java的成绩信息
步骤:1.先确定参与查询的表(分数表和课程表);2.先查询课程信息;3.通过课程编号在分数表中查询对应的分数。
sql
SELECT * FROM course WHERE `name` = 'Java' or `name` = 'MySQL';
SELECT * FROM score WHERE course_id = 1 or course_id = 3;


sql
SELECT * FROM score WHERE course_id IN (SELECT id FROM course WHERE `name` = 'Java' OR 'MySQL');

- 示例:查询不包含MySQL或Java的成绩信息
sql
SELECT * FROM score WHERE course_id NOT IN (SELECT id FROM course WHERE `name` = 'Java' OR 'MySQL');

2.4. 多列子查询
单行子查询和多行子查询都只返回一列数据,多列子查询可以返回多列个数据,外层查询与嵌套的内层查询的列要匹配。注意外层与内层列的顺序必须要对应。
- 示例:查询重复录入的分数
sql
-- 1.对重复的列进行分组
select distinct score, student_id, course_id from score GROUP BY score, student_id, course_id;
-- 2.统计分组之后每个组包含的记录数
select distinct score, student_id, course_id, count(*) from score GROUP BY score, student_id, course_id;
-- 分组中的记录数大于1,表示有重复数据
select distinct score, student_id, course_id, count(*) from score GROUP BY score, student_id, course_id having count(*) > 1;

2.5. 在from子句中使用子查询
当⼀个查询产生结果时,MySQL子动创建⼀个临时表,然后把结果集放在这个临时表中,最终返回给用户,在from⼦句中也可以使⽤临时表进行子查询或表连接操作。表连接查询时,临时表也可以参与连接,只需要确定好关联字段即可。
- 示例:查询所有比"101班"平均分高的成绩信息
我们先查出101班的班级编号,并根据班级编号在学生表查出这个班的所有学生信息。
sql
select * from student stu, class c where stu.class_id = c.id and c.`name` = '101班';

接下来根据学生id在分数表中查出所有学生的分数并计算平均分。
sql
select avg(sco.score) from
student stu, class c,score sco where
stu.class_id = c.id and c.`name` = '101班';

最后根据平均分过滤,找出比平均分高的分数。
sql
select * from score sco, (
select avg(sco.score) as score from student stu, class c,score sco where stu.class_id = c.id and c.`name` = '101班'
and sco.student_id = stu.id) as temp1 where sco.score > temp1.score;

三、合并查询
在实际应⽤中,为了合并多个select操作返回的结果,可以使用集合操作符union、union all。
3.1. 创建新表并初始化数据
sql
-- 根据现有的表创建一张新表,新表结构与老表结构一致
create table student1 like student;
-- 插入数据
insert into student1 (`name`,sno,age,gender,enroll_date,class_id) values
('Paul','10001',18,1,'2025-09-01',1),
('Bruce','30001',19,1,'2025-09-01',3),
('Ginny', '30002',19,0,'2025-09-01',3),
('Nora', '30003',18,0,'2025-09-01',3);
3.2. Union
该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。
- 示例:查询student表中id<3的同学和student1表中的所有同学
sql
select * from student where id < 3 union select * from student1;

3.3. Union all
该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。
sql
select * from student where id < 3 union all select * from student1;

四、插入查询结果
向表中写入数据时,数据是通过一个查询得到的。
4.1. 语法
sql
insert into table_name [(column [, column ...])] select ...
查询的列要与写入的匹配。
4.2. 示例
将student表中"102班"学生复制到student1表中。
sql
select stu.`name`,stu.sno, stu.age, stu.gender, stu.enroll_date, stu.class_id from student stu, class c where stu.class_id = c.id and c.`name` = '102班';
insert into student1 (`name`, sno, age, gender, enroll_date, class_id)
select stu.`name`,stu.sno, stu.age, stu.gender, stu.enroll_date, stu.class_id from student stu, class c where stu.class_id = c.id and c.`name` = '102班';