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

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

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

(一)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 语句编程如下:

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

FROM 用户表 a

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

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

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

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

Bash
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 在实际项目中的实用性,可以方便地获取多个表中的相关信息,满足不同的业务需求。

相关推荐

史上最强vue总结,面试开发全靠它了

vue框架篇vue的优点轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十kb;简单易学:国人开发,中文文档,不存在语言障碍,易于理解和学习;双向数据绑定:保留了angular的特点,...

Node.js Stream - 实战篇(node.js 10实战)

本文转自“美团点评技术团队”http://tech.meituan.com/stream-in-action.html背景前面两篇(基础篇和进阶篇)主要介绍流的基本用法和原理,本篇从应用的角度,介...

JavaScript 中的 4 种新方法指南Array.

JavaScript中的4种新方法指南Array.prototypeArray其实和Python中的l列表list的操作用非常像JavaScript语言标准的最新版本是ECMAScript...

Js基础31:内置对象(js 内置对象)

js里面的对象分成三大类:内置对象ArrayDateMath...

常见vue面试题,大厂小厂都一样(vue经典面试题)

一、谈谈你对MVVM的理解?...

最全的 Vue 面试题+详解答案(vue面试题2020例子以及答案)

前言本文整理了...

不产生新的数组,删除数组里的重复元素

数组去重的方式有很多,我们可以使用Set去重、filter过滤等,详见携程&蘑菇街&bilibili:手写数组去重、扁平化函数...

更简单的Vue3中后台动态路由 + 侧边栏渲染方案

时至今日,vue2已经升级到了vue3,动态路由的实现方案也同步做出了一些升级迭代,帮助开发者们更高效的完成业务需求,然后摸鱼。本次逻辑的升级,主要聚焦于2点更加简单的实现逻辑更加便捷的路由配置...

js常用数组API方法汇总(js数组api有哪些)

1.push()向数组末尾添加一个或多个元素,并返回新的长度。//1.push()向数组末尾添加一个或多个元素,并返回新的长度。constarr1=[1,2,3];const...

JavaScript 数组操作方法大全(js数组的用法)

数组操作是JavaScript中非常重要也非常常用的技巧。本文整理了常用的数组操作方法(包括ES6的map、forEach、every、some、filter、find、from、of等)...

Array类型简介(arrays类常用方法)

Array类型除了Object之外,Array类型恐怕是ECMAScript中最常用的类型了。而且,ECMAScript中的数组与其他多数语言中的数组有着相当大的区别。虽然ECMAScript数组与其...

鸿蒙开发基础——TypeScript Array对象解析

数组对象是使用单独的变量名来存储一系列的值。TypeScript的数组对象提供了强大的类型支持,确保数组操作的类型安全。...

js中splice的用法,使用说明及例程

js中splice的用法,使用说明及例程。splice()方法用于添加或删除数组中的元素,使用起来很怪异。删除会影响原有数组,会返回删除的内容。例1,删除数组内容:varstr=["a&#...

JavaScript 时间复杂度分析指南(js算法复杂度)

...

3个 Vue $set 的应用场景(vue中set方法应用场景)

大家好,我是大澈!一个喜欢结交朋友、喜欢编程技术和科技前沿的老程序员,关注我,科技未来或许我能帮到你!...