【图解+案例】一文搞懂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部分的内容,部分数据分析工具请翻看历史文章,更多数据分析工具的文章持续更新中,敬请期待,如果觉得不错,也欢迎分享、点赞和收藏哈~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容

  • 转载自 图解 SQL 里的各种 JOIN 从业以来主要在做客户端,用到的数据库都是表结构比较简单的 SQLite...
    kakukeme阅读 702评论 0 49
  • 一、维表join使用场景 维表Join是流与表的关联操作,为了补全流里的额外字段,通常这些待补全的维度字段很少发生...
    data之道阅读 5,859评论 1 8
  • SQL基础进阶知识 边角料(持续更新……) 强大的表连接 1、笛卡尔积 两个表每条记录一一组合,和A几几排列组合差...
    Unicornnn_阅读 229评论 0 0
  • SQL JOIN 子句用于把来自两个或多个表的行结合起来,基于这些表之间的共同字段。 最常见的 JOIN 类型:I...
    Cute_小肥鸡阅读 941评论 0 1
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,518评论 28 53