mysql在两个表分页查询内容 mysql分表联合查询_操作符


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

目录:

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

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


mysql在两个表分页查询内容 mysql分表联合查询_mysql在两个表分页查询内容_02

文中实例均以此表为例


表的加法

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

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

需要注意的2点:

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

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

我们实例来看:


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


mysql在两个表分页查询内容 mysql分表联合查询_MySQL_03


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


mysql在两个表分页查询内容 mysql分表联合查询_操作符_04


表的联结

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

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

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


mysql在两个表分页查询内容 mysql分表联合查询_mysql在两个表分页查询内容_05


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


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


mysql在两个表分页查询内容 mysql分表联合查询_mysql在两个表分页查询内容_06


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

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

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

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

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


mysql在两个表分页查询内容 mysql分表联合查询_操作符_07


mysql在两个表分页查询内容 mysql分表联合查询_mysql多表联合查询_08


1)inner join 内联结


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


mysql在两个表分页查询内容 mysql分表联合查询_MySQL_09


2)left join 左联结


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


mysql在两个表分页查询内容 mysql分表联合查询_mysql多表联合查询_10


3)right join 右联结


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


mysql在两个表分页查询内容 mysql分表联合查询_mysql多表联合查询_11


4)full join 全联结


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


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


mysql在两个表分页查询内容 mysql分表联合查询_mysql多表联合查询_12


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

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


mysql在两个表分页查询内容 mysql分表联合查询_mysql在两个表分页查询内容_13


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


mysql在两个表分页查询内容 mysql分表联合查询_mysql在两个表分页查询内容_14


case表达式

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

举例来看:

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

翻译大白话:

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


mysql在两个表分页查询内容 mysql分表联合查询_MySQL_15


② 我们对各课程的成绩按照[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以下]分段,并统计各分段数人数和课程名


mysql在两个表分页查询内容 mysql分表联合查询_mysql在两个表分页查询内容_16


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

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

实战案例

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

翻译成大白话:

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


mysql在两个表分页查询内容 mysql分表联合查询_mysql统计各部门人数_17


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

翻译成大白话:

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


mysql在两个表分页查询内容 mysql分表联合查询_操作符_18


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

翻译成大白话:

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


mysql在两个表分页查询内容 mysql分表联合查询_操作符_19


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

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


mysql在两个表分页查询内容 mysql分表联合查询_mysql在两个表分页查询内容_20


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

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



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