MySQL 表的增删改查(进阶篇②)· 联合查询 内连接 外连接 · 自连接 · 子查询 exists · 合并查询 union
接进阶篇①,我们继续学习。
- 一、联合查询
- 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;
运行结果:
以上查询只显示了成绩信息,要显示学生以及成绩信息,并且在一条语句显示:
SELECTstu.*,s1.score Java,s2.score 计算机原理
FROMscore s1JOIN score s2 ON s1.student_id = s2.student_idJOIN student stu ON s1.student_id = stu.idJOIN course c1 ON s1.course_id = c1.idJOIN course c2 ON s2.course_id = c2.idAND s1.score < s2.scoreAND 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';
运行结果:有重复行。
MySQL 表的增删改查(进阶篇②)· 联合查询 内连接 外连接 · 自连接 · 子查询 exists · 合并查询 union相关推荐
- MYSQL表的增删改查进阶(下)
MYSQL表的增删改查进阶 4. 查询 4.1 聚合查询 4.1.1 聚合函数 4.1.2 group by字句 4.1.3 having 4.2 联合查询 4.2.1 内连接 4.2.2 外连接 4 ...
- 2.MySQL表的增删改查(进阶)
这里写目录标题 MySQL表的增删改查(进阶) 1.数据库约束 2.表的设计 3.新增 4.查询 4.1 聚合查询 4.2 联合查询 5.内容重点总结 MySQL表的增删改查(进阶) 1.数据库约束 ...
- 数据库概论之MySQL表的增删改查1
MySQL表的增删改查 1.MySQL表的CRUD 2.插入数据 2.1 语法 2.2 注意事项 3.查找语句 3.1 全列查找 3.2 指定列查询 3.3 指定查询字段为表达式 3.4 查询字段指定 ...
- MySQL表的增删改查(基础)
MySQL表的增删改查(基础) 文章目录 MySQL表的增删改查(基础) 新增(`Create`) 查询(`Retrieve`) 更新(`Update`) 删除(`Delete`) 总结 注释:在SQ ...
- MySQL表的增删改查
MySQL表的增删改查 CRUD 即增加(Create).查询(Retrieve).更新(Update).删除(Delete)四个单词的首字母缩写. 表的操作,是以一套记录为基本单位: 增.删只能是以 ...
- 【MySQL系列】 MySQL表的增删改查(进阶)
目录 ??前言 ??一.数据库约束 ???1.1 约束类型 ???1.2 null约束 ???1.3 unique约束 ???1.4 default约束 ???1.5 primary key 约束 ? ...
- 【MySQL】(万字解析)MySQL表的增删改查(进阶-上)
快速跳转✅ 1.数据库的约束 1.1 约束类型 1.2 NULL约束 1.3 UNIQUE:唯一约束 1.4 DEFAULT:默认值约束 1.5 PRIMARY KEY:主键约束 1.6 FOREIG ...
- php mysql表的增删改查,PHP 之Mysql增删改查操作案例
1:user表: CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, PR ...
- MySQL - 表的增删改查(约束+聚合、联合查询)
本节目标: 数据库约束 表的关系 新增: 删除 修改 查询 1.数据库约束 1.1约束类型 NOT NULL -指示某列不能存储 NULL值. UNIQUE -保证某列的每行必须有唯一的值. DEFA ...
最新文章
- Java七步创建以JDBC连接数据库的程序
- GPT-4参数将达10兆!此表格预测全新语言模型参数将是GPT-3的57倍
- AX2009报表打印固定长度Barcode条码
- jQuery 中的 Ajax
- 在腾讯工作半年,我获得了什么?
- springcloud feign 服务调用其他服务_微服务实战——SpringCloud与Feign集成
- python填空题_Python题库-填空题
- HTML 去调table表单里面td之间的间距
- 屏幕为什么要正负压供电_焦炉煤气脱硫为什么要选择负压脱硫工艺?
- 电脑运行c语言时错误,电脑出现microsoft visual c++ runtime error 解决方法(多图)
- 浏览器内核信息和功能查看
- [渝粤教育] 西南科技大学 翻译 在线考试复习资料
- html怎么把正方形改成圆形,css怎样让div变成圆的?
- C语言怎么用char输出多个字母,c语言中char类型如何存放多个字符
- TCP可以从我们的视听感知中借鉴些什么
- 第五人格深渊金币每周更新时间
- 微信小程序点击查看大图
- 设计模式-设计原则-开闭原则是目标,里氏代换原则是基础,依赖倒转原则是手段...
- 20220509数据结构绿书读书笔记
- 王者荣耀小游戏1.0震撼上线!C++版
热门文章
- ognl表达式的简单用法
- 为什么计算机模拟试题无法评分,科目一电脑模拟打分答题
- python 做表格分析_Python 处理分析 128 张 Excel 表格竟不到3秒?| 附数据集
- 树莓派4 Ubuntu18.04安装xubuntu桌面 无线WIFI 及 ros melodic(解决apt update error,安装xubuntu error问题)
- 输入一个年份,输出是否为闰年。闰年的条件,又能被4整除但不能被100整除,或者能被400整除的年份都是闰年
- VSCode遇见的问题:chrome文件找不到/js中块级注释显示白色无效
- SitePoint播客#47:将死苹果
- Windows下使用GitHub Pages搭建hexo博客详细教程以及Next主题超全配置
- 枚举QQ或者TM进程、标题、窗口信息、QQ号码昵称等
- 50个好用的前端框架,千万收好以留备用!