700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > MySQL 表的增删改查(进阶篇②)· 联合查询 内连接 外连接 · 自连接 · 子

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

时间:2018-11-21 19:42:24

相关推荐

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

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

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

一、联合查询

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

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

我们先初始化测试数据:

insert into classes(name, `desc`) values('计算机系级1班', '学习了计算机原理、C和Java语言、数据结构和算法'),('中文系级3班','学习了中国传统文学'),('自动化级5班','学习了机械自动化');insert into student(sn, name, qq_mail, classes_id) values('09982','黑旋风李逵','xuanfeng@',1),('00835','菩提老祖',null,1),('00391','白素贞',null,1),('00031','许仙','xuxian@',1),('00054','不想毕业',null,1),('51234','好好说话','say@',2),('83223','tellme',null,2),('09527','老外学中文','foreigner@',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 子句中。

这里要用到数据查询的技巧,把一个子查询当成一个临时表来使用。

查询所有比 “中文系级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='中文系级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='中文系级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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。