MySQL数据库精研之旅第十一期:打造高效联合查询的实战宝典(二)

专栏: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班';
相关推荐
阿维的博客日记几秒前
Redis的旁路缓存策略和先删除缓存后更新数据库,先更新数据库后删除缓存,这三种策略之间有什么关系??
数据库·redis·缓存
ictI CABL17 分钟前
redis连接服务
数据库·redis·bootstrap
苍煜24 分钟前
SpringBoot单体应用到分布式下的数据库锁、事务、Redis事务、分布式锁、分布式事务协调
数据库·spring boot·分布式
xmjd msup1 小时前
mysql的分区表
数据库·mysql
Lyyaoo.1 小时前
【JAVA Spring面经】Spring 事务失效情况
java·数据库·spring
MeAT ITEM1 小时前
MySQL Workbench菜单汉化为中文
android·数据库·mysql
dovens1 小时前
PostgreSQL 中进行数据导入和导出
大数据·数据库·postgresql
IOT.FIVE.NO.11 小时前
claude code desktop cowork报错解决和记录Workspace..The isolated Linux environment ...
linux·服务器·数据库
Rick19931 小时前
mysql 慢查询怎么快速定位
android·数据库·mysql
科技小花8 小时前
全球化深水区,数据治理成为企业出海 “核心竞争力”
大数据·数据库·人工智能·数据治理·数据中台·全球化