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

SQL 中的左连接魔法:你真的会 left join 么?

wptr33 2024-11-21 22:05 22 浏览

(一)Left Join 的含义与特点

在数据库编程中,Left Join(左连接)具有独特的含义和特点。它以左表为基础,无论右表中是否有与之匹配的行,都会从左表返回所有的行。当右表中没有匹配的行时,相应的列会以 null 值填充。这一特点使得 Left Join 在数据查询和分析中非常有用,尤其是当我们需要确保左表中的数据不被遗漏时。例如,在一个电商数据库中,有订单表和客户表。如果我们想获取所有客户的信息以及他们的订单情况,使用 Left Join 可以确保即使某些客户没有下过订单,他们的信息也会被包含在查询结果中。

(二)基本语法与示例

Left Join 的基本语法通常为:“SELECT 列名 FROM 左表 LEFT JOIN 右表 ON 左表.列名 = 右表.列名”。例如,假设有两个表,学生表(students)包含学生的 ID 和姓名,成绩表(grades)包含学生的 ID 和成绩。要查询所有学生以及他们的成绩(如果有),可以使用以下语句:“SELECT students.ID, students.Name, grades.Grade FROM students LEFT JOIN grades ON students.ID = grades.ID”。查询结果中,对于有成绩的学生,会显示相应的成绩,而对于没有成绩的学生,成绩列会显示为 null。

再比如,在 MySQL 中,有文章表(article)和用户表(user)。文章表包含文章的 ID、标题和作者 ID,用户表包含用户的 ID、用户名和邮箱。要列出所有的文章及对应的所属用户,即使没有用户的文章也列出,可以使用如下语句:“SELECT article.aid,article.title,user.username FROM article LEFT JOIN user ON article.uid = user.uid”。返回的查询结果中,对于有对应用户的文章,会显示用户的用户名,而对于没有对应用户的文章,用户名列会显示为 null。

二、Left Join 的注意事项

(一)筛选条件的位置影响

在使用 Left Join 时,筛选条件放置的位置不同会导致结果产生差异。如果将筛选条件放在 ON 子句中,它主要是对右表进行条件过滤,但依然会返回左表的所有行,右表中没有匹配的则补为 NULL。例如,“SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id AND table2.name='特定名称'”,这里的条件只会影响右表的匹配内容,不影响返回行数,即左表的所有行都会被展示出来。

而如果将筛选条件放在 WHERE 子句中,是在临时表生成好后,再对临时表进行过滤。这时已经没有 Left Join 必须返回左边表记录的含义了,条件不为真的就全部过滤掉。例如,“SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id WHERE table2.name='特定名称'”,如果右表中没有满足这个条件的记录,那么左表中在右表无匹配行的记录也可能会被过滤掉。

(二)多表连接时的考量

在多个 Left Join 连接时,记录条数会发生变化,并且数据库优化器的执行顺序也需要考虑。多个 Left Join 连接时,执行顺序一般是先将左表与第一个右表进行连接,生成一个虚拟表,然后这个虚拟表再与下一个右表进行连接。例如有三个表 table1、table2、table3,执行“SELECT table1.a, table1.b, table1.c FROM table1 LEFT JOIN table2 ON table1.uid = table2.uid LEFT JOIN talbe3 ON table1.uid = table3.uid”,先将 table1 和 table2 组合成一个虚拟表,然后这个虚拟表再和 table3 关联。

关于记录条数,在没有 WHERE 语句情况下,结果条数一般会大于等于主表(即第一个左表)的条数。这是因为如果 SELECT 后面的字段均来自主表,并且所有的关联条件都是为了匹配主表。例如,假设表 A 有 100 条记录,表 B 和表 C 分别有 80 条和 60 条记录,在没有 WHERE 语句的多个 Left Join 连接下,结果条数可能会大于等于 100 条,具体取决于表之间的关联情况。如果 B 表中某个关联关键字出现了 N 次,那么在 A 表中与这个关联关键字相关的记录也会重复 N 次,从而导致结果条数增加。数据库优化器是最终决定执行顺序的地方,但一般会按照 Left Join 的顺序执行,但也不保证完全是那样。

三、Left Join 的实际应用

(一)解决一对多问题

当左表与右表存在一对多关系时,可以采用不同的方法来处理。例如,假设我们有一个用户表和一个订单表,用户表中的一个用户可能在订单表中有多个订单。如果业务需求是查询用户的下单量,可以将 SQL 语句编程如下:

SELECT a.用户 id,a.用户姓名,count(订单 id)

FROM 用户表 a

LEFT JOIN 订单表 b ON a.用户 id = b.用户 id

GROUP BY a.用户 id,a.用户姓名;

通过这种方式,将一对多的问题转化为聚合查询,统计出每个用户的订单数量。

如果业务需求是查询用户的下单明细,可以将 SQL 语句编程如下:

SELECT a.订单 id,a.业务类型,a.单价,a.消费数量,b.用户姓名,b.用户联系方式

FROM 订单表 a

LEFT JOIN 用户表 b ON a.用户 id = b.用户 id;

这样就将一对多的问题转化成多对一的问题,展示每个订单的详细信息以及对应的用户信息。

(二)条件联接查询

在面对大数据表时,运用 where 子句限定条件可以提高查询效率。有两种限定方式,一种是全量查询后 + where 子句,另一种是联接前就先做限定。

全量查询后 + where 子句的方式,如查询用户为男,消费总价大于 1w 元的用户明细:

SELECT a.订单 id,a.业务类型,a.单价,a.消费数量,b.用户姓名,b.用户联系方式

FROM 订单表 a

LEFT JOIN 用户表 b ON a.用户 id = b.用户 id

WHERE b.用户性别 = '男' AND (a.单价 * a.消费数量) > 10000 AND b.用户 id is not null;

联接前就先做限定的方式,如我们需要查询用户在某时间段,访问 A 页面再访问 B 页面的留存用户量,查询的表只有用户行为表:

SELECT count(a.user_id),count(b.user_id)

FROM (SELECT distinct user_id FROM 用户行为表 WHERE date_str = '2016 - 11 - 01' AND url = ‘A 页面路径’) a

LEFT JOIN (SELECT distinct user_id FROM 用户行为表 WHERE date_str = '2016 - 11 - 01' AND url = ‘B 页面路径’) b ON a.user_id = b.user_id

WHERE b.user_id is not null;

两种方式的差异在于,全量查询后 + where 子句是先进行左连接操作,得到一个临时结果集,然后再对这个结果集进行筛选;而联接前就先做限定是在进行左连接操作之前,先对两个表分别进行筛选,然后再进行连接操作,这样可以减少参与连接操作的数据量,提高查询效率。

(三)在实际项目中的具体案例

在实际项目中,Left Join 有很多实用的场景。比如在一个企业的人力资源管理系统中,有员工表和部门表。要查询所有员工以及他们所属的部门信息,可以使用 Left Join。假设员工表包含员工 ID、员工姓名、部门 ID 等字段,部门表包含部门 ID、部门名称等字段。使用以下 SQL 语句:

SELECT e.员工 ID,e.员工姓名,d.部门名称

FROM 员工表 e

LEFT JOIN 部门表 d ON e.部门 ID = d.部门 ID;

这样就可以得到所有员工的姓名以及他们所属的部门名称。即使某些员工没有分配部门,也会在查询结果中显示,部门名称为 null。这个例子体现了 Left Join 在实际项目中的实用性,可以方便地获取多个表中的相关信息,满足不同的业务需求。

相关推荐

HIVE 窗口函数详解(hive常用开窗函数)

什么是窗口函数窗口函数是SQL中一类特别的函数。和聚合函数相似,窗口函数的输入也是多行记录。不同的是,聚合函数的作用于由GROUPBY子句聚合的组,而窗口函数则作用于一个窗口,这里,窗口...

SQL高效使用20招:数据分析师必备技巧

基础优化技巧善用EXPLAIN分析执行计划EXPLAINSELECT*FROMordersWHEREorder_date>'2024-01-01';...

答记者问之 - Redis 的高效架构与应用模式解析

问:极客程序员你好,请帮我讲一讲redis答:redis主要涉及以下核心,我来一一揭幕Redis的高效架构与应用模式解析...

MySQL通过累计求新增(mysql新增表字段语句)

前两天的那篇内容《MySQL递归实现单列分列成多行》...

一文讲懂SQL窗口函数 大厂必考知识点

大家好,我是宁一。今天是我们的第24课:窗口函数。...

圣诞快乐:用GaussDB T 绘制一颗圣诞树,兼论高斯数据库语法兼容

转眼就是圣诞的节日,祝大家节日快乐。用GaussDBT(也就是GaussDB100)绘制一棵圣诞树,纯国产,更喜庆。话不多说,上图:SQL如下:SELECTCASEWHENENMOTE...

Minitab:功能强大的质量管理、统计分析及统计图形软件

一、Minitab简介Minitab软件是为质量改善、教育和研究应用领域提供统计软件和服务的先导,是全球领先的质量管理和六西格玛实施软件工具及持续质量改进的良好工具软件,她具有强大的功能和简易的可视化...

如何熟练使用SQL查询(如何熟练使用sql查询内容)

要熟练使用SQL查询(StructuredQueryLanguage),你需要系统地从语法入门,到实战练习,再到性能优化与多表查询的掌握。下面是一条循序渐进、实战驱动的学习路径:第一阶段:S...

SAP SE38如何在多个系统间同步代码

上一篇文章写了如何在多个系统之间同步开发对象:多套SAPERP之间一键同步ABAP开发内容,有兄弟问有没有简单办法同步SE38程序代码的,因为使用请求的方式同步代码有点小题大做了。...

Python | 垂直模态分解(phython垂直输出)

...

技术栈:刷了百道SQL题,还是不会用?你应该这样补短板

这是来自用户的提问,也是很多人遇到的困惑:...

mysql窗口函数为了解决更加复杂的问题

为了解决复杂问题的窗口函数我们先讲一下窗口函数是什么窗口和普通的函数作用相同在不同列上进行查询和返回比如我们有如下的表...

MariaDB开窗函数(开窗函数 mysql)

在使用GROUPBY子句时,总是需要将筛选的所有数据进行分组操作,它的分组作用域是整张表。分组以后,为每个组只返回一行。而使用基于窗口的操作,类似于分组,但却可以对这些"组"(即窗口...

一文掌握 DuckDB 时间序列分析:窗口函数实战详解

...

一篇文章搞定MySQL中的窗口函数(mysql常用的窗口函数)

我是孙斌,北理数学系毕业,分享数据分析相关知识,点击右上角“关注”,学习更多数据分析知识。在MySQL中,分组groupby一般和聚合函数连用,如groupby+sum,这样能够得到每个组的总和,...