前几篇文章中,我们查询的数据都是在一张表中进行操作的,而在实际工作中,我们经常需要在不同的表中查询数据,今天我们来学习从多张表中获取数据的方法--多表查询。
- 表的加法
- 表的联结
- 用SQL联结解决业务问题
- case 表达式
1.表的加法(union)
表的加法在SQL语句中用union表示,是将两个表的数据按行合并到一起。使用union语句时,重复的数据只会保留一个。若想要保留表中重复的行,则使用union all语句。
如何合并两个表?以之前的课程表(course)为 例。
打开表-修改course1数据:
合并后不保留重复值(union)结果:
如果需要保留全部重复值(union all):
2.表的联结
表和表之间是通过对应的列产生关系,这也是之前我们在设计表的时候设置的主键。其关系就是数据库中数据对应的匹配,将数据库中的表连接在一起,这种操作叫做联结(join)。
在之前的数据库school中,4张表有下面的联结关系:
通过学生表里的学号我们可以查询成绩表里对应学生的课程编号和成绩,可以通过成绩表里的课程编号对应课程表里的课程名称和教师号,又可以通过课程表里的教师号查询教师表的教师名称
表与表之间通过主键相互关联,我们就可以将他们联结在一起。
常用的联结:
- 交叉联结(cross join)
- 内联结(inner join)
- 左联结(left join)
- 右联结(right join)
- 全联结(full join)
1)交叉联结
又称为笛卡尔积。它是将一个表中的每一行分别都与另一张表中的每一行合并在一起。交叉联结后表的行数是两张表行数的乘积。
2)内联结
即同时查找出存在于两张表中的数据。
内连接示例:
as 语句并非绝对,你可以自己命名,比如可以命名为表1和表2:
3)左联结
比如这个例子,学生表里的数据和成绩表里的数据,我们如果进行左联结,左侧表中数据作为主数据,右侧表只取出相关行,也就是取出左侧取出学号,而右侧取出可联结的学号0001,再进行交叉连接,得到最终结果
若想要只取出左侧表独有数据,该怎么做?
这里我们加一个where查询条件即可
4)右联结(与左联结逻辑相反)
若想要在右联结基础上去除两表的公共数据,只取出右侧表独有数据,与左联结只取出左边独有部分的逻辑也是相反:
5)全联结
全联结的查询返回结果为左表和右表中的所有行。当某行和另一个表中有匹配的时候,会进行合并;当没有匹配的时候,另一个表的值用空值填充(注意一点,MySQL不支持全联结,了解即可)
一张图总结SQL连接(要牢记):
一般情况下我们用的是左联结或者右联结,当获取中间部分的时候用inner 联结
sql运行顺序:
3.用SQL联结解决业务问题
练习1:查询所有学生的学号、姓名、选课数、总成绩
1)翻译成大白话
- 学号、姓名来自学生表(student)
- 选课数来自成绩表(score),数目通过count计数课程号得到选课数,按学号分组
- 总成绩来自成绩表(score),总分通过sum求和,按学号分组
2)写出分析思路
两张表左联结可得到我们想要的查询结果,把对应思路写在注释里,拆解写出对应的子句
3)写出SQL语句并运行
练习2:查询平均成绩大于85的所有学生的学号、姓名和平均成绩
练习3:查询学生的选课情况:学号、姓名、课程号、课程名称
4.case表达式
使用case 表达式可以帮助我们解决复杂的查询问题, 其作用相当于一个条件判断的函数,用来判断某行数据是否满足某个条件。每次只返回一个结果。
例如:判断成绩表中成绩是否及格
练习1:查询每门课程的及格人数和不及格人数
练习2:使用分段[100-85],[85-70],[70-60],[<60]来统计各科成绩,分别统计:各分数段人数、课程号和课程名称
使用case表达式的一些注意事项:
- else子句可省略不写(默认为空值),但是尽量养成好的书写习惯不要省略,以便阅读
- 最后的end不能省略掉不写,不然会出现报错
- case表达式在刚刚的案例里是放在了select子句中作为条件判断,但case表达式作用不止在此,在SQL语句的任意子句中都可以运用哦!
写在最后:
干货虽多,也要多多练习来巩固所学,快去sqlzoo 去练习起来吧~