MySQL 表的增删改查(进阶篇②)· 联合查询 内连接 外连接 · 自连接 · 子查询 exists · 合并查询 union

news2024/9/27 5:50:10

接进阶篇①,我们继续学习。

  • 一、联合查询
    • 1.1 内连接
    • 1.2 外连接
    • 1.3 内连接和左右外连接的区别
  • 二、自连接
  • 三、子查询
    • 3.1 单行子查询
    • 3.2 多行子查询
      • 使用 in 范围匹配多行
      • 另一种写法 exists
      • 两种写法的区别
    • 3.3 在 from 子句中使用子查询
  • 四、合并查询
    • union
    • union all

一、联合查询

实际开发中往往数据来自不同的表,所以需要多表联合查询。

多表查询是对多张表的数据取笛卡尔积。

我们先初始化测试数据:

insert into classes(name, `desc`) values
('计算机系2019级1班', '学习了计算机原理、C和Java语言、数据结构和算法'),
('中文系2019级3班','学习了中国传统文学'),
('自动化2019级5班','学习了机械自动化');

insert into student(sn, name, qq_mail, classes_id) values
('09982','黑旋风李逵','xuanfeng@qq.com',1),
('00835','菩提老祖',null,1),
('00391','白素贞',null,1),
('00031','许仙','xuxian@qq.com',1),
('00054','不想毕业',null,1),
('51234','好好说话','say@qq.com',2),
('83223','tellme',null,2),
('09527','老外学中文','foreigner@qq.com',2);
insert into course(name) values
('Java'),('中国传统文化'),('计算机原理'),('语文'),('高阶数学'),('英文');

insert into score(score, student_id, course_id) values
-- 黑旋风李逵
(70.5, 1, 1),(98.5, 1, 3),(33, 1, 5),(98, 1, 6),
-- 菩提老祖
(60, 2, 1),(59.5, 2, 5),
-- 白素贞
(33, 3, 1),(68, 3, 3),(99, 3, 5),
-- 许仙
(67, 4, 1),(23, 4, 3),(56, 4, 5),(72, 4, 6),
-- 不想毕业
(81, 5, 1),(37, 5, 5),
-- 好好说话
(56, 6, 2),(43, 6, 4),(79, 6, 6),
-- tellme
(80, 7, 2),(92, 7, 6);

1.1 内连接

语法:

select 字段 from 表1 别名1 [inner] join 表2 别名2 on 连接条件 and 其它条件;
select 字段 from 表1 别名1,表2 别名2 where 连接条件 and 其它条件;

案例一: 查询 “许仙” 同学的成绩.

-- 写法一
select student.name,score.score from student,score where student.id=score.student_id and student.name='许仙';

--写法二
select student.name,score.score from student inner join score on student.id=score.student_id and student.name='许仙';

运行结果:

解析:

首先,我们需要判断出会涉及到哪些表,学生表和成绩表

其次,将两个表先进行笛卡尔积操作(会出现很多数据);

select * from student,score;

接着,给 sql 语句添加连接条件,将无意义的数据过滤掉;

select * from student,score where student.id=score.student_id;

然后,逐渐添加题目中的其它条件(学生名字),一步步缩小数据范围;

select * from student,score where student.id=score.student_id and student.name='许仙';

最后再精简查询的列,就是最后的答案。

select student.name,score.score from student,score where student.id=score.student_id and student.name='许仙';

案例二: 查询所有同学的总成绩,以及同学的个人信息

-- 成绩表对学生表是 n 对 1 关系,查询总成绩需要根据成绩表的同学 id 来进行分组的
select stu.sn,stu.name,stu.qq_mail,sum(sco.score) from student stu,score sco where stu.id=sco.student_id group by sco.student_id;

执行结果:


案例三: 查询所有同学的成绩,以及同学的个人信息。

-- 学生表、成绩表、课程表 3 张表关联查询
select stu.sn,stu.name,stu.qq_mail,sco.score,sco.course_id,cou.name 
	from student stu,score sco,course cou 
	where stu.id=sco.student_id and cou.id=sco.course_id;

运行结果:


1.2 外连接

外连接分为左外连接和右外连接。
如果联合查询,左侧的表完全显示我们称为左外连接;右侧的表完全显示我们称为右外连接。

语法:

-- 左外连接
select 字段名 from 表名1 left join 表名2 on 连接条件;
-- 右外连接
select 字段 from 表名1 right join 表名2 on 连接条件;

案例: 查询所有同学的成绩,以及同学的个人信息。如果该同学没有成绩,也需要显示。

select stu.id,stu.sn,stu.name,stu.qq_mail,sco.score,sco.course_id,cou.name 
from student stu 
	left join score sco on stu.id=sco.student_id 
	left join course cou on sco.course_id=cou.id 
order by stu.id;

运行结果:


1.3 内连接和左右外连接的区别

假设两个表的每一条数据都是一一对应的,此时外连接和内连接是等价的。
如果有时候可能存在一些数据,没有对应关系,内外连接就有差别了。

例如:

内连接: 两个表内连接,有个没有成绩的同学没有显示出来。

左外连接: 一共 21 条记录,“老外学中文” 同学可以显示出来。

右外连接: 一共 21 条记录,“老外学中文” 同学可以显示出来。

观察案例可以发现,内连接的结果只包含在两张表都有体现的数据;
左外连接,左侧的表的数据是全的;
右外连接,右侧的表的数据是全的。



二、自连接

自连接是指在同一张表连接自身进行查询。

案例: 查询所有 “计算机原理” 成绩比 “Java” 成绩高的成绩信息。

select s1.student_id, s1.score as java, s2.score as '计算机原理' 
from score s1, score s2 
where s1.student_id = s2.student_id 
	and s1.course_id=1 
	and s2.course_id=3 
	and s1.score<s2.score;

-- join on 语句的写法来进行自连接查询
select s1.student_id,
	s1.score as java,
	s2.score as '计算机原理' 
from score s1 join score s2 
on s1.student_id=s2.student_id 
	and s1.score < s2.score 
	and s1.course_id=1 
	and s2.course_id=3;

运行结果:

以上查询只显示了成绩信息,要显示学生以及成绩信息,并且在一条语句显示:

SELECT
	stu.*,
	s1.score Java,
	s2.score 计算机原理
FROM
	score s1
	JOIN score s2 ON s1.student_id = s2.student_id
	JOIN student stu ON s1.student_id = stu.id
	JOIN course c1 ON s1.course_id = c1.id
	JOIN course c2 ON s2.course_id = c2.id
	AND s1.score < s2.score
	AND c1.NAME = 'Java'
	AND c2.NAME = '计算机原理';

运行结果:



三、子查询

子查询是指嵌入在其它 sql 语句中的 select 语句,也叫嵌套查询。

3.1 单行子查询

返回一行记录的子查询

查询与 “不想毕业” 同学的同班同学

select * from student where classes_id=(
	select classes_id from student where name='不想毕业');


3.2 多行子查询

返回多行记录的子查询

使用 in 范围匹配多行

查询 “语文” 或者 “英文” 课程的成绩信息

select * from score where course_id in (
	select id from course where name='语文' or name='英文');

执行结果:

另一种写法 exists

也可以完成多行子查询

select * from score 
where exists(
	select score,course_id from course 
	where(name='英文' or name='语文') 
	and course.id=score.course_id
);

执行过程:

先执行外层查询,就会得到很多行记录。

每获取到外层查询的一行,就都会执行一次子查询的 SQL。

接下来,如果子查询的结果集合为空,那么外层查询的这一行记录,就被忽略。
如果子查询的结果集合非空,那么外层查询的这一行记录就会被记录。

exists 效果就是检测,先获取数据,在把数据一条一条的执行子查询 SQL,筛选掉不符合子查询的数据。


两种写法的区别

第一种基于 in 的写法,速度快,但是如果子查询的结果集合很大,内存放不下,就凉了。

第二种,基于 exists 的写法,速度慢,但是和内存的关系不大,哪怕子查询很大,也能保证执行出结果。

如果子查询结果集合比较小,优先使用第一种写法。

如果子查询结果集合比较大,并且外层查询的结果数量比较少,优先考虑第二种写法。


3.3 在 from 子句中使用子查询

子查询语句出现在 from 子句中。
这里要用到数据查询的技巧,把一个子查询当成一个临时表来使用。

查询所有比 “中文系2019级3班” 平均分高的成绩信息:

select avg(sco.score) score 
from score sco 
	join student stu on sco.student_id=stu.id 
	join classes cls on stu.classes_id=cls.id 
where cls.name='中文系2019级3班';

查询成绩表中,比以上临时表平均分高的成绩:

select * from score sco,(
	select avg(sco.score) score 
	from score sco 
		join student stu on sco.student_id=stu.id 
		join classes cls on stu.classes_id=cls.id 
	where cls.name='中文系2019级3班'
)tmp where sco.score > tmp.score;


四、合并查询

在实际应用中,为了合并多个 select 的执行结果,可以使用集合操作符 union,union all。
使用 union,union all 时,前后查询的结果集,字段需要保持一致。

union

该操作符用于取得两个结果集的并集。使用该操作符的时候,会自动去掉结果集中重复的行。

查询 id 小于 3,或者名字为 ‘英文’ 的课程

select * from course where id<3 
union 
select * from course where name='英文';

执行结果:

其实使用 or 来实现更加简单。

select * from course where id<3 or name='英文';

union all

该操作符用于取得两个结果集的并集。
当使用此操作符的时候,不会去掉结果集中的重复行。

查询 id 小于 3,或者名字为 ‘Java’ 的课程

select * from course where id<3 union all select * from course where name='Java';

运行结果:有重复行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/127177.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

随谈_前端与后端

文章目录一、前言二、前后端分别是什么&#xff1f;2.1. 前端&#xff08;front end&#xff09;2.2. 后端&#xff08;back end&#xff09;一、前言 最近在学习Vue&#xff0c;打算边学边用&#xff0c;开发一个网页系统。 Vue的话&#xff0c;网上介绍很多&#xff0c;简单…

容器安全的三大挑战

容器凭借其经济高效的优势改变了应用程序的交付方式&#xff0c;随着容器的普遍使用&#xff0c;管理应用程序基础设施的 IT 劳动力和资源也显著减少。然而&#xff0c;在保护容器和容器化生态系统时&#xff0c;软件团队遇到了许多障碍。尤其是习惯于更传统的网络安全流程和策…

MYSQL学习之路

MYSQL架构示意图 MYSQL8.0开始移除了查询缓存这个模块&#xff1b; 查询缓存&#xff1a;适合读多写少的任务&#xff1b; 建议&#xff1a;将 have_query_cache 设置为No&#xff0c;在需要使用查询缓存的语句上显式声明&#xff1b; select SQL_CACHE * from test;WAL(Write …

mysql sql优化、查看索引、创建索引

1.索引遵循原则 仅在被频繁检索的字段上创建索引。针对大数据量的表创建索引&#xff0c;而不是针对只有少量数据的表创建索引。通常来说&#xff0c;经常查询的记录数目少于表中总记录数据的 15% 时&#xff0c;可以创建索引。这个比例并不绝对&#xff0c;它与全表扫描速度成…

java:jackson 一:Jackson Annotation

java&#xff1a;jackson 一&#xff1a;Jackson Annotation 1 前言 参考文档地址&#xff1a; https://www.baeldung.com/jacksonhttps://www.baeldung.com/jackson-annotations2 使用 2.1 Jackson Serialization Annotations jackson 序列化注解 2.1.1 JsonAnyGetter T…

产业互联网是以大数据、云计算、AI等为代表的数字技术的出现为标志

事实上&#xff0c;以往&#xff0c;我们所经历的那个互联网玩家频出的年代&#xff0c;其实就是一个以互联网技术为主导的年代。在那样一个年代里&#xff0c;互联网技术几乎是解决一切痛点和难题的万能解药&#xff0c;几乎是破解一切行业痛点和难题的杀手锏。任何一个行业&a…

数据可视化③:大学生就业数据分析

大学生就业是和我们息息相关的话题&#xff0c;每一位大学生都关注着&#xff0c;我们常常在网络上看到有关大学生就业的话题&#xff0c;比如毕业季的一些讨论。在大一的创新创业课中&#xff0c;我们也了解到自己所学的专业和以后如何就业&#xff0c;往哪方面就业。但我们了…

深度学习目标检测_IOU、Precision、Recall、AP、mAP详解

文章目录背景IOU&#xff1a;Intersection Over Unionprecision&#xff08;精度&#xff09;和recall&#xff08;召回率&#xff09;TP、TN 、FP 、FNAP和mAP首先回顾两个概念PR曲线AP(Average Precision&#xff09;mAP(mean Average Precision)背景 目标检测的任务是找出图…

[oeasy]python0035_ 整合shell编程_循环_延迟_清屏

整合shell编程 回忆上次内容 用\r 可以让输出位置回到行首原位刷新时间 如果想要的是大字符效果 需要使用 figlet但同时还希望能刷新这可能吗&#xff1f;&#x1f914; 建立脚本 我们得熟悉一下shell 先新建一个test.sh vi test.sh python3 show_time.py python3 show_time.…

如何通过GB35114国密标准接入到LiveGBS GB28181/GB35114监控平台

1.1 安装LiveGBS GB28181/GB35114视频平台 1.2 获取设备端证书给平台 我们用LiveNVR做为设备端向LiveGBS注册&#xff0c;这里先将LiveNVR的证书导出&#xff0c;并给LiveGBS端。 本地自签名证书是LiveNVR自己给自己签发的证书。如果需要用第三方机构的证书&#xff0c;可点击…

【软件测试】资深测试的总结,有限时间找最有价值bug......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 测试团队的新同事&a…

Mybatis进阶之自定义TypeHandler

实际应用开发中的难免会有一些需求要自定义一个TypeHandler &#xff0c;比如这样一个需求&#xff1a;前端传来的性别是 男, 女&#xff0c;但是数据库定义的字段却是tinyint 类型&#xff08; 1:男 2:女&#xff09;。此时可以自定义一个年龄的类型处理器&#xff0c;进行转换…

Linux学习笔记——Linux实用操作(一)

04、Linux实用操作 4.1、各类小技巧&#xff08;快捷键&#xff09; 学习目标&#xff1a; 掌握各类实用小技巧 强制停止退出、登出历史命令搜索光标移动 1、Ctrlc强制停止 Linux某些程序的运行&#xff0c;如果想要强制停止它&#xff0c;可以使用快捷键Ctrlc 命令输入…

一个基于Vue+SpringBoot的个人博客项目,含数据库文件

blogSpringBoot 项目介绍 完整代码下载地址&#xff1a;一个基于VueSpringBoot的个人博客项目&#xff0c;含数据库文件 该项目是个人博客项目&#xff0c;采用Vue SpringBoot开发。 后台管理页面使用Vue编写&#xff0c;其他页面使用Thymeleaf模板。 项目演示地址&#…

什么是 MySQL 的“回表”?

1. 索引结构 要搞明白这个问题&#xff0c;需要大家首先明白 MySQL 中索引存储的数据结构。这个其实很多小伙伴可能也都听说过&#xff0c;BTree 嘛&#xff01; BTree 是什么&#xff1f;那你得先明白什么是 B-Tree&#xff0c;来看如下一张图&#xff1a; 前面是 B-Tree&am…

不止稳定快速,看华为云CDN如何在国际云服务市场中“分蛋糕”

互联网时代&#xff0c;网络的应用已十分普及&#xff0c;但依然存在下载慢、网络卡顿的现象。如企业业务运行过程中出现的卡顿现象导致数据延时&#xff1b;各校因疫情等原因网课时间长、访问应用人数过多&#xff0c;造成网络卡顿现象严重&#xff0c;无法带来良好的上课体验…

ArcGIS基础实验操作100例--实验16对字段自定义赋值

本实验专栏来自于汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 基础编辑篇--实验16 对字段自定义赋值 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1…

玩转云服务器,怎样用云服务器架设搭建游戏:浪剑天下架设教程,手把手教你架设游戏服务器,小白一看就会

服务器详情&#xff1a;服务器系统&#xff1a;LINUX-CENTOS7.6服务器配置&#xff1a;2核4G以上配置 搭建教程&#xff1a; 第一步&#xff1a;安装宝塔&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh &…

Allegro如何输出IPC文件操作指导

Allegro如何输出IPC文件操作指导 IPC文件是PCB上所有网络连接关系文件,在PCB生产前网表比对必须的文件,如下图 如何输出IPC文件,具体操作如下 选择File选择IPC356

磁实验比较-反激式变压器(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…