百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

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

mhr18 2024-09-20 20:57 34 浏览 0 评论

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

相关推荐

B站收藏视频失效?mybili 收藏夹备份神器完整部署指南

本内容来源于@什么值得买APP,观点仅代表作者本人|作者:羊刀仙很多B站用户都有过类似经历:自己精心收藏的视频突然“消失”,点开一看不是“已被删除”,就是“因UP主设置不可见”。而B站并不会主动通知...

中间件推荐初始化配置

Redis推荐初始化配置bind0.0.0.0protected-modeyesport6379tcp-backlog511timeout300tcp-keepalive300...

Redis中缓存穿透问题与解决方法

缓存穿透问题概述在Redis作为缓存使用时,缓存穿透是常见问题。正常查询流程是先从Redis缓存获取数据,若有则直接使用;若没有则去数据库查询,查到后存入缓存。但当请求的数据在缓存和数据库中都...

后端开发必看!Redis 哨兵机制如何保障系统高可用?

你是否曾在项目中遇到过Redis主服务器突然宕机,导致整个业务系统出现数据读取异常、响应延迟甚至服务中断的情况?面对这样的突发状况,作为互联网大厂的后端开发人员,如何快速恢复服务、保障系统的高可用...

Redis合集-大Key处理建议

以下是Redis大Key问题的全流程解决方案,涵盖检测、处理、优化及预防策略,结合代码示例和最佳实践:一、大Key的定义与风险1.大Key判定标准数据类型大Key阈值风险场景S...

深入解析跳跃表:Redis里的&quot;老六&quot;数据结构,专治各种不服

大家好,我是你们的码农段子手,今天要给大家讲一个Redis世界里最会"跳科目三"的数据结构——跳跃表(SkipList)。这货表面上是个青铜,实际上是个王者,连红黑树见了都要喊声大哥。...

Redis 中 AOF 持久化技术原理全解析,看完你就懂了!

你在使用Redis的过程中,有没有担心过数据丢失的问题?尤其是在服务器突然宕机、意外断电等情况发生时,那些还没来得及持久化的数据,是不是让你夜不能寐?别担心,Redis的AOF持久化技术就是...

Redis合集-必备的几款运维工具

Redis在应用Redis时,经常会面临的运维工作,包括Redis的运行状态监控,数据迁移,主从集群、切片集群的部署和运维。接下来,从这三个方面,介绍一些工具。先来学习下监控Redis实时...

别再纠结线程池大小 + 线程数量了,没有固定公式的!

我们在百度上能很轻易地搜索到以下线程池设置大小的理论:在一台服务器上我们按照以下设置CPU密集型的程序-核心数+1I/O密集型的程序-核心数*2你不会真的按照这个理论来设置线程池的...

网络编程—IO多路复用详解

假如你想了解IO多路复用,那本文或许可以帮助你本文的最大目的就是想要把select、epoll在执行过程中干了什么叙述出来,所以具体的代码不会涉及,毕竟不同语言的接口有所区别。基础知识IO多路复用涉及...

5分钟学会C/C++多线程编程进程和线程

前言对线程有基本的理解简单的C++面向过程编程能力创造单个简单的线程。创造单个带参数的线程。如何等待线程结束。创造多个线程,并使用互斥量来防止资源抢占。会使用之后,直接跳到“汇总”,复制模板来用就行...

尽情阅读,技术进阶,详解mmap的原理

1.一句话概括mmapmmap的作用,在应用这一层,是让你把文件的某一段,当作内存一样来访问。将文件映射到物理内存,将进程虚拟空间映射到那块内存。这样,进程不仅能像访问内存一样读写文件,多个进程...

C++11多线程知识点总结

一、多线程的基本概念1、进程与线程的区别和联系进程:进程是一个动态的过程,是一个活动的实体。简单来说,一个应用程序的运行就可以被看做是一个进程;线程:是运行中的实际的任务执行者。可以说,进程中包含了多...

微服务高可用的2个关键技巧,你一定用得上

概述上一篇文章讲了一个朋友公司使用SpringCloud架构遇到问题的一个真实案例,虽然不是什么大的技术问题,但如果对一些东西理解的不深刻,还真会犯一些错误。这篇文章我们来聊聊在微服务架构中,到底如...

Java线程间如何共享与传递数据

1、背景在日常SpringBoot应用或者Java应用开发中,使用多线程编程有很多好处,比如可以同时处理多个任务,提高程序的并发性;可以充分利用计算机的多核处理器,使得程序能够更好地利用计算机的资源,...

取消回复欢迎 发表评论: