当前位置:   article > 正文

mysql多表联合查询_MySQL数分:多表查询

查询不及格的课程名称有哪些,多表联合查询

fdeb13063fa000de6f898f6e5017d710.png

上次我们对MySQL的复杂查询进行介绍,包括前期的课程也都是对一个表进行操作。本节,我们继续对MySQL基础知识深入学习:如何对多表进行查询

目录:

  • 表的加法
  • 表的联结
  • case表达式
  • 实战案例

本文我们在前期的例子中先增加一个course_add表。

e1e93ab6d7ebd78c8973154a95737343.png
文中实例均以此表为例

表的加法

我们现在有两张课程表分别是课程表course 和 课程表course_add,现在我们想要知道所有的课程都有哪些,我们需要把两张表相加并且不显示重复项,这里我们使用union操作符:

union操作符可以合并多个select语句的结果集。

需要注意的2点:

union内部的select语句必须有相同数量的列;列名顺序必须相同且数据类型必须相似

一般默认union操作符相加的是不同的值,如果允许重复需要全部显示,可以使用union all操作符

我们实例来看:

-- 把课程表course 和 course_add 结合,不允许重复

fa4b789421ea2312e3709e6f416db398.png
-- 把课程表course 和 course_add 结合,允许重复

faba94a68ef761e497a21fb37f7d69d9.png

表的联结

我们现在想要知道每个学生每门功课的成绩,我们需要把学生表student和成绩表score中获取结果,得到一个更加完整的表,从完整表中查询学生的成绩。这里我们介绍新的关键词——join

join 用于根据多个表中的列之间的关系,从这些表中查询数据。

在我们的数据表实例中,各表之间都存在关系,是因为有主键key将这些表联系起来:

10a134108b6c6a1fd818fe8299984eee.png

现在,我们把学生表student和成绩表score进行交叉联结:

-- 用join把学生表student和成绩表score交叉联结,显示学生成绩

2f6c2a243a3e9e716159c6ff63986d1b.png

我们看到,现在每个学生的“学号”“姓名”“课程号”和“成绩”就都显示出来了。

除了上述实例中的join联结,还有其他的联结方式,下面我列出所有的联结方式:

  • inner join 内联结:返回两个表可匹配的行;
  • left join 左联结:即使左表没有匹配,右表返回所有行;
  • right join右联结:即使右表没有匹配,左表返回所有行;
  • full join 全联结:只要其中某个表存在匹配九返回所有行;

接下来我们依次实例来说明:

为了可以更明显的显示结果,我们对student表和score表进行补充:

27f28c9e98c99e565accfad832189bca.png

d71b6f6b98c9481b5fbdd6040e26bd72.png

1)inner join 内联结

-- 用inner join把学生表student和成绩表score交叉联结,显示学生成绩

486150fbd50577f56c708b23fb4b1d54.png

2)left join 左联结

-- 用left join把学生表student和成绩表score交叉联结,显示学生成绩

3de75d9b2e9777dae6ac3171428c316b.png

3)right join 右联结

-- 用right join把学生表student和成绩表score交叉联结,显示学生成绩

4cf8bdc4a80906c3c1a995034341b984.png

4)full join 全联结

-- 用full join把学生表student和成绩表score交叉联结,显示学生成绩

但是,你会发现,报错了···

f9e7baa0b47d66815ad559bbbb336955.png

别慌,这是因为MySQL没有full join这个东东~所以呢,如果你又特别想把两个表全部联结,可以使用union all,但是union又有两个需要注意的事项:“union内部的select语句必须有相同数量的列;列名顺序必须相同且数据类型必须相似”,所以我们需要分两个步骤:

student表的所有行,与score的非匹配部分的行相加,或许不好理解,我们看图:(绿色线条所在面积+灰色线条所在面积)

7acef52f0c70d62797525532e4ac97b7.png
  • ① 使用左联结 left join取绿色部分面积;
  • ②使用右联结right union 条件为左列名为null的部分面积;
  • ③ 使用union all 相加
/* ① 使用左联结 left join取绿色部分面积;

e2b3992f260705c0b17cc8a2960c4555.png

case表达式

先说一下case表达式的作用,就像Excel中的if语句和Python中的if···else···语句,case表达式是SQL中的逻辑判断语句。

举例来看:

我们想要查询出每门课程的及格人数和不及格人数:

翻译大白话:

  • 定义条件:成绩>=60分及格,成绩<60分不及格;
  • 按课程号进行分组,对分组结果的人数按照上一步的逻辑条件计数;
# 

a86ff731b58d7c5508a7fc103976ece1.png

② 我们对各课程的成绩按照[100-85(含)]、[85-70(含)]、[70-60(含)]、[60以下]分段,并统计各分段数人数和课程名

翻译大白话:

  • 定义条件:成绩在100-85(含)为[100-85(含)]段,在85-70(含)为[85-70(含)]段,在70-60(含)为[70-60(含)]段,小于60就是[60以下]分段;
  • 把成绩表score和课程表course交叉联结(右联结),显示课程号、课程名、和分数段;
  • 按课程号、课程名进行分组,对分组结果的人数按照上上述的逻辑条件计数;
-- 对各课程的成绩按照[100-85(含)]、[85-70(含)]、[70-60(含)]、[60以下]分段,并统计各分段数人数和课程名

e6e9108893ac69dcad5faba9c0b284cb.png

这么看来,多变联结是不是也蛮简单呢?

现在,我们就用几个实例来试试吧~

实战案例

1. 查询所有学生的学号、姓名、选课数、总成绩

翻译成大白话:

  • 将学生表student和成绩表score交叉联结(左联结),显示学号、姓名、课程号、成绩;
  • 按照学生号分组,对分组结果按照课程号计数;并对所有课程成绩求和;
-- 查询所有学生的学号、姓名、选课数、总成绩

573a9a26e1554efeb8eec3430548eb9d.png

2.查询平均成绩大于85的所有学生的学号、姓名和平均成绩

翻译成大白话:

  • 将学生表student和成绩表score交叉联结(左联结),显示学号、姓名、成绩;
  • 按照学生号分组,对分组结果按照成绩求均值;
  • 对所得结果指定条件要求平均成绩大于85分;
-- 查询平均成绩大于85的所有学生的学号、姓名和平均成绩

06391990434f252288ab1f75c920e25e.png

3.查询学生的选课情况:学号,姓名,课程号,课程名称

翻译成大白话:

  • 将学生表student和成绩表score交叉联结(内联结),显示学号、姓名、课程号;
  • 将上步的结果再与课程表course交叉联结(内联结),显示学号、姓名、课程号、课程名;
-- 查询学生的选课情况:学号,姓名,课程号,课程名称

97b97db21fa04baa1462e8e65806b97d.png

接下来的案例来自The JOIN operation,数据库里存了2012年欧洲杯赛事和入球信息:

三个表,分别是赛事表game、入球表goal、队伍表eteam,各边联系见下:

91da426538a6cdbca9a0c9f3dd994232.png

我们对下边的练习题一一解答:

1.在进球表(goal)中查找德国球队(teamid = 'GER')进球的比赛编号(matchid),进球球员姓名(player):

select 

2. 在比赛信息表(game)查找比赛编号1012的信息:

SELECT 

3.查找德国队进球球员姓名,球队编号(在进球信息表goal), 比赛地点,比赛日期(在比赛信息表game):

  • 入球表goal和赛事表game交叉连结(内联结),显示球员姓名player、球队编号teamid、比赛地点stadium、比赛日期mdate;
  • 对查找结果按照条件“德国GER”来筛选;
select 

4.查找姓名中以Mario开头的进球球员,符合条件球员参加比赛的对战双方:

  • 入球表goal和赛事表game根据赛事编号进行交叉连结(内联结),显示符合条件的球队名team1、team2及球员姓名;
  • 筛选条件为入球表中player以Mario开头;
select 

5.查找进球球员的姓名、球队编号、教练、多长时间进球。要求多长时间进球<=10分钟:

  • 入球表goal和队伍表eteam根据队伍编号(teamid&id)交叉联结(内联结),显示球员姓名player、球队编号teamid、教练coach、入球时间gtime;
  • 筛选条件为入球时间<=10;
select 

6.'Fernando Santos'作为team1教练的比赛日期,球队编号有哪些?

  • 队伍表eteam和赛事表game通过队伍编号(team1&id)交叉联结(内联结),显示比赛日期mdate和球队编号teamname
select 

7.在比赛地点'National Stadium, Warsaw'有哪些进球球员?

  • 赛事表game与进球表goal通过赛事编号(matchid&id)交叉联结(内联结),显示球员姓名player;
  • 筛选条件为赛场stadium为'National Stadium, Warsaw';
select 

8..射入德国球门的球员姓名

  • 赛事表game与进球表goal通过赛事编号(matchid&id)交叉联结(内联结),显示球员姓名player;
  • 筛选条件为team1或者team2中有一个是“GER”;
select 

9.列出球队名称,和每个球队进球数;

  • 进球表goal和队伍表eteam通过队伍编号(teamid&id)交叉联结(内联结),显示球队名称teamname和进球数(count(player))
  • 按球队名teamname分组,对分组结果的球员名出线次数计数;
select 

10.查找出所有比赛地点,每个比赛地点的进球数:

  • 赛事表game与进球表goal通过赛事编号(matchid&id)交叉联结(内联结),显示赛场stadium和进球数(count(player));
  • 按赛场stadium分组,对分组结果的球员名出线次数计数;
select 

11.查找出有波兰球队'POL'参加的比赛编号,比赛日期,对应这场比赛的进球数:

  • 赛事表game与进球表goal通过赛事编号(matchid&id)交叉联结(内联结),显示赛事编号matchid、比赛日期mdate、进球数(count(player));
  • 按赛事编号matchid分组,对分组结果的球员名出线次数计数;
  • 筛选条件为队伍team1或者team2中任意一个是'POL';
select 

12. 对于德国队'GER'得分的每场比赛,显示比赛编号,比赛日期和'GER'得分的进球数:

  • 赛事表game与进球表goal通过赛事编号(matchid&id)交叉联结(内联结),显示赛事编号matchid,比赛日期mdate、进球数(count(player));
  • 按赛事编号matchid分组,对分组结果的球员名出线次数计数;
  • 筛选条件为队伍tteamid为'GER';
select 

13.查找出所有比赛的日期,每场比赛中对战双方各自的进球数(也就是team1进球数,team2进球数),并按照结果排序:

  • 定义条件:如果team1的球队出线在进球表goal,team1 得分;如果team2的球队出线在进球表goal,team2 得分;
  • 赛事表game与进球表goal通过赛事编号(matchid&id)交叉联结(左联结),显示比赛日期mdate、赛事编号matchid、team1、score1(team1得分)、team2,score2(team2得分);
  • 按赛事编号matchid、比赛日期mdate、team1、team2分组;
  • 按赛事编号matchid、比赛日期mdate、team1、team2排序;
select 

好啦,本次分享就到这里啦~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/435288?site
推荐阅读
相关标签
  

闽ICP备14008679号