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班';
相关推荐
郭俊强5 分钟前
nestjs 连接redis
数据库·redis·缓存
海边捡石子13 分钟前
postgress数据迁移gaussdb注意事项
数据库
小猿姐21 分钟前
KubeBlocks For MySQL 云原生设计分享
mysql·云原生·架构
chen_note26 分钟前
Redis数据持久化——RDB快照和Aof日志追加
java·数据库·mybatis·持久化·aof·rdb
携欢1 小时前
PortSwigger靶场之SQL injection with filter bypass via XML encoding通关秘籍
xml·数据库·sql
GBASE1 小时前
GBASE南大通用技术分享:GBase 8s数据库Q转义功能解析(上)
数据库
Java水解1 小时前
MySQL 中的 UPDATE 语句
后端·mysql
闲人编程1 小时前
PyQt6 进阶篇:构建现代化、功能强大的桌面应用
数据库·python·oracle·gui·脚本·pyqt6·软件
speop1 小时前
【datawhale组队学习】RAG技术 -TASK05 向量数据库实践(第三章3、4节)
数据库·学习
EnigmaCoder1 小时前
【Linux】用户与用户组管理
linux·运维·服务器·数据库