上一节讲了SQL简单查询,包括SQL语句的分类、基本查询语句(select)、条件语句、运算符等。本节讲一下多表查询。
举个工作中的实际例子,假设你在做一款贷款产品,这里有两张表:用户表(userinfo)、借款还款表(loanapp)。你想查询所有用户的借款总笔数、借款总金额,就需要以用户作为关联条件,从三张表里面查找相应的数据进行分析。具体如何实现?看完下面的内容你就能轻松解决这个问题。
1.表的加法
表的加法是指按行,将表合并在一起,通过关键字union实现。现在,这里有两张格式一样的表,你想把两张表的数据合并起来,该如何操作?
先写语句再解释,如下:
select 学生姓名,学生编号 --注释:选择course1表的两列数据
from 表1
union--注释:合并
select 学生姓名,学生编号 --注释:选择course1表的两列数据
from 表2;
运行结果如下:
注意:
表1 中有两行数据,表2 中有三行数据,加起来是五行数据,但是运行出来的结果只有四行数据。这是因为关键字【union】会把表里面重复的数据去重。如果你想保存重复的行,将【union】改为【union all】即可。
2.表的联结
之前介绍过,关系数据库中,表和表之间是通过关系列关联起来的(哪里都要靠这种关键节点,数据库中是,生活中也是这样,有关系好办事。。。)
有了关系列后,就可以把不同的表联结起来,常见的联结方式有以下几种:
交叉联结、内连接、做链接、右联结、全联结,我们逐一介绍。
交叉联结(cross join)
又称为笛卡尔积,作用是将一个表中的每一行,和另一个表中的每一行合并在一起。交叉联结后的总行数,是两张表的行数的乘机,举个例子:
两个表交叉联结后的结果如下:
可以看到,联结后的展示的内容,是将两个表的内容拼起来。表的行数是两张表的行数的乘机:1*2=2.如果第一张表有5行,第二张表有3行,那么两张表交叉联结后的行数为:5*3=15.
说明:
交叉联结在实际业务中用的比较少,因为交叉联结产生的数据太多了,需要耗费很多设备、时间成本计算。而且,交叉联结会产生很多无意义的数据。但是,交叉联结是我们接下来要说的几种联结方式的基础,因此还是有必要了解清楚。
内联结(inner join)
作用是选取出同时存在于两张表中的数据,选取后按照交叉联结的方式合并展示出来。
举个例子,现在有两张表,如下:一张学生信息表,一张学生成绩表,现在你想查出某个学生的信息和成绩,如何用inner join实现?
这里先写语句:
select学生信息表.学号,学生信息表.姓名,学生成绩表.学号,学生成绩表.课程,学生成绩表.成绩--选择要拼接的列,为了方便区别这个列是哪张表的,需在列名前边加表名
from学生信息表inner join学生成绩表--选择拼接的表
on学生信息表.学号 = 学生成绩表.学号;--选择以哪个列作为拼接条件
上面两张表的名称太长,不管在书写还是在阅读上都不方便,能不能给它们起一个临时名称,以方便书写?这里可以用关键字as来实现,写法如下;
select a.学号,a.姓名,b.学号,b.课程,b.成绩--选择要拼接的列,为了方便区别这个列是哪张表的,需在列名前边加表名
from学生信息表as a inner join学生成绩表as b--选择拼接的表
on a.学号 = b.学号;--选择以哪个列作为拼接条件
通过以上语句,运行处的结果如下:
说名:
内联结的SQL 语句运行顺序如下:
- 将两个表里面【学号】相同的列的数据都取出来。
- 将两个表里面取出的数据合并,使用交叉联结的方式合并。
- 将一个表中的所有行与另个表中所有合并在一起。
左联结
左联结是将左侧表作为主表,并指定主表的某一列为【关联列】。运行时,主表的数据全部读出来;右边表的数据按照【关联列】进行选取,与【关联列】相同的数据会被选取,不同的数据不会被选取。选取之后,两个表的数据按照交叉联结的方式合并展示。
举个例子,,现在有两张表,如下:一张学生信息表,一张学生成绩表,现在通过左联结将以下两张表合并后的结果会是怎样?
先公布语句写法:
select a.学号,a.姓名,b.学号,b.课程,b.成绩
from学生信息表as a left join 学生成绩表as b
on a.学号 =b.学号;
可以发现语句和写法和inner join类似。通过以上语句,运行处的结果如下:
因为学号0002在右边的表里没有对应的行,所以合并后,对应的位置显示空值。如果你想删除掉有空值的行,可以通过where字句增加一个筛选条件,如下:
selecta.学号,a.姓名,b.学号,b.课程,b.成绩f
rom学生信息表asaleftjoin学生成绩表asb
ona.学号 = b.学号
whereb.学号 =null;
右联结
右联结是将右侧表作为主表,并指定主表的某一列为【关联列】。运行时,主表的数据全部读出来;左边表的数据按照【关联列】进行选取,与【关联列】相同的数据会被选取,不同的数据不会被选取。选取之后,两个表的数据按照交叉联结的方式合并展示。
具体的写法与左联结类似,我这里就不再举例了,大家可以自己打开Navicat写一写。
全联结
全联结会返回两个表的所有行。当A表【关联列】的值与B表【关联列】的值相等时,按照交叉联结合并显示。
当A表【关联列】的值与B表【关联列】的值不相等时,另一个表中对应地方的值用控制来填充。(类似左联结和右联结的结合)
举个例子:
全联结后显示的结果为:
说明:MYSQL是不支持全联结的。一般来说,全联结应用场景也不多。
3. 案例解答
回到文章一开始的问题:
假设你在做一款贷款产品,这里有两张表:用户表(userinfo)、借款还款表(loanapp)。你想查询所有用户的借款总笔数、借款总金额,就需要以用户作为关联条件,从三张表里面查找相应的数据进行分析。具体如何实现?
说明:遇到问题的时候,一定不能上来就写SQL语句,这里有一个三步走分析模型,分享给大家:
1. 拆解问题—2. 写出分析思路—3. 写出对应的SQL字句
1. 拆解问题
以上问题拆分成三个关键部分:所有用户,借款总笔数,借款总金额
2. 分析思路
所有用户:用户ID,用户姓名,在userinfo查询
借款总笔数:按照用户ID分组,对借款编号按照笔数计数(count)
借款总金额:按照用户ID分组,对借款金额求和(sum)
3. 写出SQL语句
selecta.ID,a.姓名,b.ID,count(借款编号)as借款总笔数,sum(借款金额)as借款总金额fromuserinfoasaleftjoinloanappasbona.ID = B.ID
groupbya.ID;
到此为止,简单查询和多表查询告一段落。在以后的文章中,我会尽量举一些工作中的实例,由浅入深,与大家一起深入掌握这门语言。接下来将分享复杂查询,和一些实战数据分析。如果有写的不对的地方,欢迎指正。也希望你持续关注,公号:数据产品经理之路。