SQL 中的左连接魔法:你真的会 left join 么?
wptr33 2024-11-21 22:05 23 浏览
(一)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 在实际项目中的实用性,可以方便地获取多个表中的相关信息,满足不同的业务需求。
相关推荐
- python数据容器之列表、元组、字符串
-
数据容器分为5类,分别是:列表(list)、元组(tuple)、字符串(str)、集合(set)、字典(dict)list#字面量[元素1,元素2,元素3,……]...
- 深入理解 PYTHON 虚拟机:令人拍案叫绝的字节码设计
-
深入理解PYTHON虚拟机:令人拍案叫绝的字节码设计在本篇文章当中主要给大家介绍cpython虚拟机对于字节码的设计以及在调试过程当中一个比较重要的字段co_lnotab的设计原理!PYT...
- Python快速学习第一天!
-
第一天:Python是一种解释型的、面向对象的、带有动态语义的高级程序设计语言一、运行Python:1、在交互式环境下,直接输入Python进入Python编程环境[root@tanggao/]#...
- Java 程序员的第一套Python代码
-
选择的Web组件是Python里面的Django,这不一定是一个最佳的框架或者最快的框架,当时他应该算是一个最成熟的框架。...
- Python 中 必须掌握的 20 个核心函数及其含义,不允许你不会
-
以下是Python中必须掌握的20个核心函数及其含义...
- Python代码:按和值奇偶比对号码进行组合
-
Python代码:按和值奇偶比对号码进行组合不少朋友在选定号码以后,会按照一定的和值来组号,比如大乐透常见和值有626372737481108116等我们不用固定在一个数上,我们可以给定...
- 30天学会Python编程:16. Python常用标准库使用教程
-
16.1collections模块16.1.1高级数据结构16.1.2示例...
- Python强大的内置模块collections
-
1.模块说明collections是Python的一个内置模块,所谓内置模块的意思是指Python内部封装好的模块,无需安装即可直接使用。...
- Python自动化办公应用学习笔记31—全局变量和局部变量
-
一个Python程序中的变量包括两类:全局变量和局部变量。一、全局变量·...
- 精通Python可视化爬虫:Selenium实战全攻略
-
在数据驱动的时代,爬虫技术成为获取信息的强大武器。而Python作为编程界的“瑞士军刀”,搭配Selenium库,更是让我们在动态网页抓取领域如鱼得水。本文将带你深入探索PythonSelenium...
- Python中的数据类型操作
-
...
- Python教程(二十五):装饰器–函数的高级用法
-
今天您将学习什么...
- 玩转Python列表/字典:增删改查与高效遍历技巧
-
为什么列表和字典是Python的灵魂?你是否遇到过这样的场景?想存储学生成绩,用列表却发现查找某个学生的分数像大海捞针?用字典存储购物车商品,却不知道如何高效批量修改价格?遍历数据时,传统循环写得...
- Python列表操作
-
Python添加列表4分钟阅读在Python操作列表有各种方法。例如–简单地将一个列表的元素附加到...
- 充分利用Python多进程提高并发
-
在计算机编程中,我们经常需要同时执行多个任务。然而,传统的单线程方式无法充分利用计算机的多核处理器,导致程序的执行效率低下。Python中的多进程编程技术可以帮助我们解决这个问题,通过同时运行多个进程...
- 一周热门
-
-
因果推断Matching方式实现代码 因果推断模型
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)