【联合查询】
文章目录
- 一、简介
- 1、为什么要使⽤联合查询
- 2、多表联合查询时MYSQL内部是如何进⾏计算的
- 3、构造练习案例数据
- 4、案例:⼀个完整的联合查询的过程
- 二、内连接
- 1、语法
- 2、⽰例
- 三、外连接
- 1、语法
- 2、⽰例
- 四、⾃连接
- 1、应⽤场景
- 2、⽰例
- 3、表连接练习
- 五、⼦查询
- 1、语法
- 2、单⾏⼦查询
- 3、多⾏⼦查询
- 4、多列⼦查询
- 5、在from⼦句中使⽤⼦查询
- 六、合并查询
- 1、创建新表并初始化数据
- 2、Union
- 3、Union all
- 七、插⼊查询结果
- 1、语法
- 2、⽰例
一、简介
1、为什么要使⽤联合查询
在数据设计时由于范式的要求,数据被拆分到多个表中,那么要查询⼀个条数据的完整信息,就要从多个表中获取数据,如下图所⽰:要获取学⽣的基本信息和班级信息就要从学⽣表和班级表中获取,这时就需要使⽤联合查询,这⾥的联合指的是多个表的组合。
2、多表联合查询时MYSQL内部是如何进⾏计算的
- 参与查询的所有表取笛卡尔积,结果集在临时表中(全排列)
- 观察哪些记录是有效数据,根据两个表的关联关系过滤掉⽆效数据
如果联合查询表的个数越多,表中的数据量越⼤,临时表就会越⼤,所以根据实际情况确定联合查询表的个数
3、构造练习案例数据
(1)课程表
(2)班级表
(3)学⽣表
(4)成绩表
4、案例:⼀个完整的联合查询的过程
- 查询学⽣姓名为孙悟空的详细信息,包括学⽣个⼈信息和班级信息
(1)确定参与查询的表,学⽣表和班级表(在from后同时写所有参与查询的表,并⽤逗号隔开)
(2)确定连接条件,student表中的class_id与class表中id列的值相等(在where⼦句中加⼊连接条件)
(3)加⼊查询条件
依题意添加where条件
由于两个表中都有name列,所以MySQL不清楚具体要使⽤哪个列,这时可以⽤“表名.列号”的⽅式指定具体的列
得到⽬标记录⾏
(4)精减查询结果字段
(5)可以为表名指定别名
二、内连接
1、语法
2、⽰例
- 查询"唐三藏"同学的成绩
- 查询所有同学的总成绩,及同学的个⼈信息
Group by 使⽤了student.id进⾏分组,查询表列表中的student.name没有出现在Group by分组中,也没有包含在聚合函数中,这是因为SQL规定在Group by分组查询时,如果查询列表中的列没有出现在GROUP BY⼦句中,但这些列的值在每个分组内部是相同的,那么它们可以出现在查询结果中。- 查询所有同学每⻔课的成绩,及同学的个⼈信息(结果集中没有"不想毕业"同学的成绩,因为score表中没有这位同学的记录)
(1)确定哪几张表参与查询
学生表、课程表、成绩表
(2)根据表与表之间的关系,确定过滤条件
三、外连接
- 外连接分为左外连接、右外连接和全外连接三种类型,MySQL不⽀持全外连接。
- 左外连接:返回左表的所有记录和右表中匹配的记录。如果右表中没有匹配的记录,则结果集中对应字段会显⽰为NULL。(以左表为基准,无论右表是否匹配,左表中的数据都会查出来)
- 右外连接:与左外连接相反,返回右表的所有记录和左表中匹配的记录。如果左表中没有匹配的记录,则结果集中对应字段会显⽰为NULL。
- 全外连接:结合了左外连接和右外连接的特点,返回左右表中的所有记录。如果某⼀边表中没有匹配的记录,则结果集中对应字段会显⽰为NULL。
1、语法
2、⽰例
- 查询没有参加考试的同学信息
(1)左连接以JOIN左边的表为基准,左表显⽰全部记录,右表中没有匹配的记录⽤NULL填充
(2)过滤参加了考试的同学
- 查询没有学⽣的班级
(1)右连接以JOIN右边的表为基准,右表显⽰全部记录,左表中没有匹配的记录⽤NULL填充
(2)过滤有学⽣的班级
四、⾃连接
1、应⽤场景
⾃连接是⾃⼰与⾃⼰取笛卡尔积,可以把⾏转化成列,在查询的时候可以使⽤where条件对结果进⾏过滤,或者说实现⾏与⾏之间的⽐较。在做表连接时为表起不同的别名。
(1)不为表指定别名
(2)指定别名
确定连接条件,两个表中的student_id必须要相同
2、⽰例
- 显⽰所有"MySQL"成绩⽐"JAVA"成绩⾼的成绩信息
(1)⾸先分两步进⾏,先查出JAVA和MySQL的课程Id,分别为1和3
(2)再查询成绩表中,JAVA成绩⽐MySQL成绩好的信息
(3)结合在⼀起进⾏查询
3、表连接练习
- 显⽰所有"MySQL"成绩⽐"JAVA"成绩⾼的学⽣信息和班级以及成绩信息
(1)相关的表全部加⼊连接,并确定连接条件
五、⼦查询
⼦查询是把⼀个SELECT语句的结果当做别⼀个SELECT语句的条件,也叫嵌套查询
1、语法
2、单⾏⼦查询
嵌套的查询中只返回⼀⾏数据
- ⽰例:查询与"不想毕业"同学的同班同学
- 过滤掉“不想毕业”这位同学的记录
3、多⾏⼦查询
嵌套的查询中返回多⾏数据,使⽤[NOT] IN关键字
- ⽰例:查询"MySQL"或"Java"课程的成绩信息
(1)使⽤NOT IN 可以查询除了"MySQL"或"Java"课程的成绩
4、多列⼦查询
单⾏⼦查询和多⾏⼦查询都只返回⼀列数据,多列⼦查询中可以返回多个列的数据,外层查询与嵌套
的内层查询的列要匹配
- ⽰例:查询重复录⼊的分数
(1)插⼊重复的分数:score, student_id, course_id列重复
- 补充:如何去重数据
- 解题思路:
(2)⼦查询中返回多个列
5、在from⼦句中使⽤⼦查询
当⼀个查询产⽣结果时,MySQL⾃动创建⼀个临时表,然后把结果集放在这个临时表中,最终返回
给⽤⼾,在from⼦句中也可以使⽤临时表进⾏⼦查询或表连接操作
- ⽰例:查询所有⽐"Java001班"平均分⾼的成绩信息
(1)⾸先分步进⾏,第⼀步先查出Java001班的平均分
先从班级表中根据班级名查出班级编号;根据班级编号在学生表中找到属于这个班级的学生,并获取学生编号;根据学生编号在分数表中计算平均分。
(2)把以上查询做为临时表,与真实表进⾏⽐较
tmp 是临时表的别名
六、合并查询
在实际应⽤中,为了合并多个select操作返回的结果(最终返回一个结果集),可以使⽤集合操作符 union,union all
1、创建新表并初始化数据
(1)创建⼀个新表并初始化数据
2、Union
该操作符⽤于取得两个结果集的并集。当使⽤该操作符时,会⾃动去掉结果集中的重复⾏。
- ⽰例:查询student表中 id < 3 的同学和student1表中的所有同学
(1)结果集中有两张表中的数据,但是唐三藏只返回了⼀条记录
3、Union all
该操作符⽤于取得两个结果集的并集。当使⽤该操作符时,不会去掉结果集中的重复⾏。
(1)结果集中有两张表中的数据,返回了所有唐三藏的记录
七、插⼊查询结果
1、语法
2、⽰例
- 将student表中C++001班的学⽣复制到student1表中
补充:
以上是本篇文章的全部内容,如果文章有错误或者有看不懂的地方,多和喵博主交流。互相学习互相进步。如果这篇文章对你有帮助,可以给喵博主一个关注,你们的支持是我最大的动力。