「图解+案例」一文搞懂SQL各种表连接join

01写在前面

SQL作为数据分析师必备技能之一,无论是初级分析师还是高级分析师,SQL已经是各大公司招聘条件里的必选项,为什么SQL对于数据分析师来说如此重要呢?在回答这个问题之前,我们先搞懂以下几个问题。

第一个问题,SQL是啥?

SQL是Structured Query Language的缩写,意思是结构化查询语言,是一种在数据库管理系统(RelationalDatabase Management System, RDBMS)中查询数据,或通过RDBMS对数据库中的数据进行更改的语言。

看不懂。。。能不能说人话?好嘞,SQL就是一种对数据库中的数据表或者数据进行增、删、改、查等操作的语言。

什么是数据库?“数据库是“按照数据结构来组织、存储和管理数据的仓库”。是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。说人话就是按照一定的组织结构存储数据的仓库。我们常见的Oracle,MySQL,SQL Server都是数据库,只是有一些是商业的数据库,一些是开源免费的而已。

第二个问题,数据分析为啥要学SQL?

其实理解了数据库和SQL的关系之后,这个问题就是句废话了。巧妇难为无米之炊,数据分析的第一步肯定是要有数据,数据哪里来?肯定要从数据库中取出来,SQL就是这样一个方便、普适的取数工具,因为几乎所有的数据库的SQL语法都是相似的,甚至现在我们做大数据分析用到的Hive SQL,其语法99%也是和SQL一样的,所以学会SQL基本上就掌握了所有数据库的取数方法。

第三个问题,到底怎么学习SQL?

你以为SQL只是一个简单的取数工具,把数据从数据库中拉出来就完事了?

1、SQL不仅能取数据,还提供了丰富的函数,可以做数据的清洗、转换等数据处理,而且SQL还能像Excel的透视表那样,可以方便地在不同的维度上对数据进行求和、计数、去重计数、求平均等操作,进而对数据进行分析,而这一切,也只需要短短的几行SQL代码就能实现。

2、如果数据很多很复杂,像Excel那样存放在不同的Sheet里,要汇总在一起进行分析,要怎么处理呢?SQL的强大之处就在于可以非常方便地将不同的数据按照一定的关联连接起来,这个关联可以是内连接inner join (找两个表的交集)、左连接left join (交集并且左表所有)、右连接(right join 交集并且右表所有)、全连接outer join(找两个表的并集),可以通过各种不同的关联条件可以实现各种不同的数据连接,最终对连接后的数据进行分析。

3、通过以上两点来看,SQL好像和Excel功能上没啥区别啊?Excel也能做数据清洗,透视表也能做求和、计数等聚合操作,Excel的Power Pivot也能实现多个表之间的连接。实际上,SQL除了以上这些功能之外,还提供了一个非常强大的功能:窗口函数,窗口函数有什么用呢?如果我们要计算每个人在特定分组下的排名、每月销售额的同比、环比、截至每天的累计销售额,这些数据分析中经常遇到的、且基础的SQL语句无法很好解决的问题,窗口函数就显示出它的威力了。所以窗口函数也是判断你是SQL基础玩家和高阶玩家的重要标准,也是数据分析面试中最喜欢考查的内容之一。

那么想入行数据分析的同学来说,怎么快速高效地掌握SQL这个数据分析的利器呢?根据前面的介绍,提升SQL水平可以按照这样的学习路径:

1、SQL基础语法:首先熟悉SQL的基础语法,对于数据分析而言,重点掌握数据查询SELECT,包括:如何使用WHERE进行数据筛选,熟练使用算数运算符(+-*/)、逻辑运算符(AND /OR/NOT)进行字段计算和条件过滤,使用SUM 、COUNT、AVG等聚合函数结合GROUP BY进行不同维度下的汇总分析,如何用HAVING子句对聚合的结果进行过滤,并使用ORDER BY 对最终的查询结果进行排序。这一部分最最重要的一点是:要明确SQL语句的执行顺序与书写顺序的差异,这一点对于了解SQL的执行过程很有帮助。作为SQL系列文章的第一篇内容,我们会在本文中重点讲解。

2、SQL常用函数:在掌握了SQL基础语法的基础上,下面就要熟练掌握一些数据分析中常用的函数,包括但不限于:日期类函数、字符串类函数,数值运算类函数等。熟练使用这些函数可以帮助我们高效地做数据的清洗、转换等数据处理工作。这部分内容我们会在SQL系列文章的第二篇重点讲解。

3、SQL子查询与表连接:在之前的基础上,我们还要熟练掌握子查询和多个表之间的连接。数据分析工作中,往往需要对多张有关联的表进行分析,对于简单的查询,我们可以使用嵌套的子查询解决。但如果涉及的表很多,且表之间的关联关系比较复杂,我们就需要使用表连接,按照一定的关联关系将各个表连接在一起,常见的连接类型有内连接:INNER JOIN 、左连接:LEFT JOIN、右连接:RIGHT JOIN 、全连接:FULL JOIN。这部分内容我们会在SQL系列文章的第三篇文章中重点讲解。

4、SQL窗口函数:前面三部分基本上已经涵盖了数据分析对于SQL的基础要求,但是实际工作中,我们有一些比较复杂且常见的场景,使用基础语法并不能很好的解决,比如:每月销售额的同比/环比、截至每天的累计销售额、每种商品在它所属分类下的销售额排名,窗口函数就是为这些场景而生的,如果能熟练掌握窗口函数,数据分析中就基本上不会遇到什么SQL的问题了。这部分内容作为SQL系列文章的压轴,会在第四篇文章中重点讲解。

另外,前面已经总结了一些数据分析中常用的Excel使用技巧,有兴趣的可以翻看之前的文章。

02、为什么要进行表连接join?

在数据库设计中,如果涉及到较多的业务表,为了防止相同数据在多个表中同时存放,减少数据冗余和存储浪费,通常会将不同的数据放在不同的表中,对数据进行拆解分别存储。

但在分析的过程中,为了获取完整的分析数据,我们就需要从多表中取数据,将多个表连接成一个表,方便我们进行分析。所以连接查询是SQL查询语句中最常见、运用最广泛的查询技巧。

根据表的连接方式划分,将表连接分为内连接、外连接,下图为连接方式的细分。

在进行实际案例演示之前,我们先对各种连接的原理和使用场景做个介绍。

03、内连接INNER JOIN

内连接inner join使用连接运算符匹配两个表共有的列,返回两个表中均满足连接条件的记录,若不满足条件则不返回。

内连接按照连接方式的不同,又可以分为以下几种:

等值连接:在连接条件中使用等号(=)运算符连接两个表中相同的列,返回两个表共同满足连接条件的所有行。

非等值连接:在连接条件使用除等于运算符以外的其它比较运算符进行连接的情况,包括>、>=、<=、<、!>、!<和<>,均为非等值连接。

自连接:有时在查询时需要自身和自身连接(自连接),这个时候我们要为同一个表定义不同的别名以示区分。

笛卡尔积连接:两张表中的每一条记录和另外一个表进行笛卡尔积组合,然后根据WHERE条件过滤结果集中的记录。

在所有的内连接类型中最典型、最常用的内连接方式是等值连接,也就是连接条件ON中的匹配类型为等值“=”匹配,等值连接返回两个表中共同字段值相等的所有行。

如下图所示,表A和B进行等值连接后,返回的是两个表中满足连接条件的共用部分C,即交集。

还是通过之前产品销售案例说明,我们有一张产品销售表product记录了用户产品的销售信息,产品维表dim_product记录了产品的供应商信息,如果表A、B按照product_id列进行等值连接,连接过程和结果如下所示。

下面我们通过实际的代码进行说明。

产品销售表product表我们之前已经构建,如果不清楚表结构和数据的可以翻看上一篇文章,这里我们需要构建一个记录产品供应商信息的产品维表dim_product。

--1、 在数据库Sales创建表,用于存放演示的数据

USE Sales;

-- 2、创建产品维表dim_product

CREATE TABLE dim_product

(

product_id CHAR(4) NOT NULL,-- 产品id,字符类型CHAR

supplier VARCHAR(100) NOT NULL,-- 产品供应商,字符类型VARCHAR

production_date DATE -- 产品生产日期,日期类型DATE

);

-- 3、插入一些用于演示的数据,只是用来演示说明,并无实际意义和真实性。

INSERT INTO dim_product VALUES (0001,sup_A,2021-03-01);

INSERT INTO dim_product VALUES (0003, sup_A, 2021-04-01);

INSERT INTO dim_product VALUES (0004, sup_B, 2021-05-01);

INSERT INTO dim_product VALUES (0010, sup_C, 2021-06-01);

创建完dim_product后,我们完成产品销售表product和产品维表dim_product的等值连接,皆可获得各产品的供应商信息,代码和结果如下:

-- 通过product_id进行等值连接

select

A.product_id AS A_product_id,

A.sale_date,

B.product_id AS B_product_id,

B.supplier

from product A

inner join dim_product B

on A.product_id = B.product_id;

结果如下:结果中并没有出现product_id为0002和0010的记录

04、外连接Left/Right/Full Join

除了内连接以外,在实际的工作中,即使是在连接条件不满足的情况下,我们也希望能够返回结果,这个时候就要用到外连接。

常见的外连接主要有左、右、全连接,区别如下:

1、左/右连接:LEFT/RIGHT JOIN

左连接left join或left outer join 对左表不加限制,结果返回左表的所有行,如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。

如下图所示,以表A为左表,和B进行左连接后,返回的是左表的所有行,如果B表中没有满足连接条件的,将B表中的各列置为空值。

相对地,对于右连接,right join 或right outer join 对右表不加限制,结果返回右表的所有行,如果右表的某行在左表中没有匹配行,则在相关联的结果集行中左表的所有选择列表列均为空值,示意如下:

左连接和右连接是相对的,一般来说,我们在使用中主要用左连接,所以接下来主要以左连接为例进行说明。

还是通过之前产品销售案例说明,我们用产品销售表product作为左表,和产品维表dim_product按照product_id列进行左连接,连接过程和结果如下所示。

下面我们通过实际的代码进行说明。

-- 通过product_id进行左连接

select

A.product_id AS A_product_id,

A.sale_date,

B.product_id AS B_product_id,

B.supplier

from product A

left join dim_product B

on A.product_id = B.product_id;

结果如下:A表中product_id为0002的记录仍然返回。

2、全连接 FULL JOIN

除了上述内连接、左右连接外,有时候我们想把两个表中所有的记录都返回,这时就需要用到全连接 full join 或者full outer join。

全连接full join对左、右表均不加限制,连接返回左表和右表中的所有行。如果表之间有匹配行,则返回共同的匹配行,当某行在另一个表中没有匹配行时,则另一个表的选择列表列置为空值。

如下图所示,表A和表B进行全连接后,返回的是两表中的所有行,即A、B表的并集。

还是通过之前产品销售案例说明,我们用产品销售表product作为左表,和产品维表dim_product按照product_id列进行左连接,连接过程和结果如下所示。

需要注意的是:Oracle数据库支持full join,MySQL是不支持full join的,如果需要full join可以通过左连接+ union+右连接实现。

所以这里我们通过左连接和右连接实现。

-- MySQL的实现方式

select

A.product_id AS A_product_id,

A.sale_date,

B.product_id AS B_product_id,

B.supplier

from product A

left join dim_product B

on A.product_id = B.product_id

union

select

A.product_id AS A_product_id,

A.sale_date,

B.product_id AS B_product_id,

B.supplier

from product A

right join dim_product B

on A.product_id = B.product_id

;

-- Oracle的实现方式通过product_id进行全连接

select

A.product_id AS A_product_id,

A.sale_date,

B.product_id AS B_product_id,

B.supplier

from product A

full join dim_product B

on A.product_id = B.product_id

;

结果如下:A表和B表中的列都返回了,在对方表里找不到的字段全部置为NULL。

以上就是数据分析工具—SQL常用的表连接join部分的内容,部分数据分析工具请翻看历史文章,更多数据分析工具的文章持续更新中,敬请期待,如果觉得不错,也欢迎分享、点赞和收藏哈~

举报/反馈