SQL中的内连接(inner join)、外连接(left|right join、full join)以及on关键字中涉及分区筛选、null解释

一、简介

本篇幅主要介绍了:

  1. SQL中内连接(inner join)、外连接(left join、right join、full join)的机制;
  2. 连接关键字on上涉及表分区筛选的物理执行及引擎优化;
  3. null在表关联时的情况与执行;

内容适用于常见大数据计算引擎,诸如hive、tez、sparksql、presto(trino)等。考虑到后续引擎版本迭代,具体执行以物理执行计划为准,查看执行计划只需再SQL最前方加上explain关键字即可,比如:explain select t1.id,t2.id as id2 from tablename1 t1 join tablename2 t2 on t1.id=t2.id

阅读者适用于SQL入门还没弃坑的同学。

二、有关sql中null的解读

1. 空这个概念

sql中,人们称之为,一般有三种解释:

  1. 空字符串,''
  2. 不合理,不存在,比如小孩的年龄,如果xx用户都没有小孩,那就不存在这个概念了
  3. 不确定,未知。sql中的null一般做该中解释,未知意味着null与null以及任何只与null的判断都是返回null;sql中的null只能用is null才能返回true

比如:select 5>null;
在这里插入图片描述
select null=null也是返回null
在这里插入图片描述
select null is null返回true
在这里插入图片描述

2. 当null出现在逻辑and和or条件里

and 两边都是true才返回true;
select 1>null and true返回null
在这里插入图片描述

or 两边只要有一边是true就返回true;
select 1>null or true 返回true
在这里插入图片描述

3. and和or的优先级

where field_name1 is not null and field_name2>100 or field_name3 is not null and field_name4>0 or field_name5 is not null

这段sql判断逻辑等于:where (field_name1 is not null and field_name2>100) or (field_name3 is not null and field_name4>0) or field_name5 is not null

先and前后判断,最后剩下几个or的或关系

为提升可读性,当涉及多个and,or条件判断时,尽量用括号括起来(如上);

如果条件放在join的on里边作用一样;

select t1.id,t2.id,t2.field_name2 
from tablename1 t1 
join tablename2 t2 
on 1=null and t1.id=t2.id and t1.dt='20241109' and t2.dt='20241109' and t1.id>100 or t2.id<300

以上sql返回t2.id<300的笛卡尔交集

三、连接机制介绍

首先理解内连接和外连接的机制,然后再看on关键字的作用;on关键字的条件只是判断在什么情况下两个表的记录行会产生关联行为;

有表:tablename1tablename2,两个表都是分区表,且两个表的分区字段名都是dt

1. 内连接:inner join

取交集

样例sql:

select t1.id,t2.id,t2.field_name2 
from tablename1 t1 
join tablename2 t2 
on t1.id=t2.id and t1.dt='20241109' and t2.dt='20241109' and t1.id>100

等于(这个t1.id>100是在join之前得tablescan中filter筛选的):
sql1:

select t1.id,t2.id,t2.field_name2 
from tablename1 t1 
join tablename2 t2 
on t1.id=t2.id 
where  t1.dt='20241109' and t2.dt='20241109' and t1.id>100 and t2.id is not null

等于sql2:

select t1.id,t2.id,t2.field_name2 
from (select id from tablename1 where dt='20241109' and t1.id>100) t1 
join (select id,field_name2 from tablename2 where dt='20241109' and is not null) t2 
on t1.id=t2.id

需要注意的是,有一种sql写法,表里没有join,实际也是按inner join走的,比如下面这段sql:

select t1.appid,t1.target,t1.sq,t2.product_type
from ads_mg_core_target_value t1 ,dim_game_info t2 
where t1.appid=t2.appid

我们打印下执行计划:

explain select t1.appid,t1.target,t1.sq,t2.product_type
from ads_mg_core_target_value t1 ,dim_game_info t2 
where t1.appid=t2.appid

在这里插入图片描述
我这里装的是单机hive,且表体量都很小,所以打印的执行计划最后走的是mapjoin

我们把自动mapjoin给关掉,再看下:set hive.auto.convert.join=false;

在这里插入图片描述
这时候显示的是reduce join了

以上三个sql案例,两个表都只读了20241109一个分区的数据,且t1.id>100都是在读分区map时扫描过滤的(引擎优化)

因为null与任何的判断最终都是返回null(除了isnull判断),所以当sql不涉及isnull判断时,对于on量表关联的字段,引擎会做优化,在tablescan表扫描时将null值给剔掉,故inner join不存在null的倾斜(在map时全剔掉了)

在这里插入图片描述

2. 左右连接:left join | right join

left join 跟right join的机制大致等同,一个保留左表全部数据(left join),一个保留右表全部数据(right join)

我们还是以上面的sql为案例,改成left join
sql-1

select t1.id,t2.id,t2.field_name2 
from tablename1 t1 
left join tablename2 t2 
on t1.id=t2.id and t1.dt='20241109' and t2.dt='20241109' and t1.id>100

这段sql如果t1表全量数据体量很大,那就是灾难了,tablename1全表扫描,因为left join保留左表全部数据。大概率是写sql的人sql写错了;tablename2表只读了一个分区;对于not (t1.dt='20241109' and t1.id>100)部门,on没有符合的条件,t2.field_name2全都是null;

不等于
sql-2

select t1.id,t2.id,t2.field_name2 
from tablename1 t1 
left join tablename2 t2 
on t1.id=t2.id 
where t1.dt='20241109' and t2.dt='20241109' and t1.id>100

等于sql-3:

select t1.id,t2.id,t2.field_name2 
from tablename1 t1 
left join tablename2 t2 
on t1.id=t2.id and t1.dt='20241109' and  t1.id>100
where t2.dt='20241109'

等于sql-4:

select t1.id,t2.id,t2.field_name2 
from tablename1 t1 
join (select * from tablename2 where dt='20241109' where id is not null) t2 
on t1.id=t2.id and t1.dt='20241109' and  t1.id>100

3. 全连接:full join

全量接,左右会保留左右两边表的所有记录行,对于on关联不上的,被关联表的字段返回null。
sql-1

select t1.id,t2.id,t2.field_name2 
from tablename1 t1 
full join tablename2 t2 
on t1.id=t2.id and t1.dt='20241109' and t2.dt='20241109' and t1.id>100

这个表最后就是tablename1和tablename2两个表都全表扫描,只有当on条件成立是才会映射被关联表字段,其他关联不上的,被关联表该字段都是null;

如果要筛选分区及条件后再用id full join,只能先用子查询改写再join

select  t1.id,t2.id,t2.field_name2 
from (select t1.id from tablename1 where id>100 and dt='20241109') t1 
full join (select id,field_name2 from tablename2 where dt='20241109') t2 
on t1.id=t2.id 

现在有两个表:
在这里插入图片描述
两个表用id字段full join,也就是t1 full join t2 on t1.id=t2.id

那么结果返回几条呢?

因为null与任何非isnull判断都是返回null,full join保留左右表全部数据,所以该段sql一共返回6行数据,测试sql:

select t1.id as t1_id,t2.id as t2_id 
from 
(select null as idunion all select 1 as id union all select 2 as id 
) t1 
full join 
(select 2 as idunion all select null as id union all select null as id union all select 4 as id 
) t2
on t1.id=t2.id 
order by t1.id desc,t2.id desc 

实际返回如下:

在这里插入图片描述

4. left semi join

这是一种特殊的join,sql中in/exists的实现。相比普通inner join,匹配到一条数据就无须再尝试匹配其他数据了。inner join遇到重复会发散;left semi join只会返回左表的部分(仅on的key参与计算);语法支持的情况,也可以用in去改写。具体看执行计划。

5. 多表关联

当存在多表关联时,一般的执行顺序是从左往右走,比如:

tablename1 t1 
left join tablename2 t2
on t1.id=t2.id 
join tablenamme3 t3
on t1.id2=t3.id2

先t1跟t2 left join,结果再跟t3 join;

有的引擎会基于成本优化,调整join顺序,以上sql可能物理执行时这样的(因为两者结果是等同的,如果t2表很小,t3表很大,可能会做出这种优化,具体看物理执行):

tablename1 t1 
join tablenamme3 t3
on t1.id2=t3.id2
left join tablename2 t2
on t1.id=t2.id 

也会有一种情况,如果多表关联on的关联条件是相同的,比如(都是id):

tablename1 t1 
left join tablename2 t2
on t1.id=t2.id 
join tablenamme3 t3
on t1.id=t3.id

看起来有两个join,实际在大数据中,只跑了一段mr,map时读取三个表的数据,reduce左两个join的关联再返回。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/58815.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习(一)——基本概念、模型的评估与选择

目录 1 关于2 概念2.1 基础概念2.2 学习过程2.3 预测与评估2.4 标记与分类2.4.1 标记2.4.2 分类 2.5 回归分析2.6 聚类分析2.7 学习类型2.8 泛化能力2.9 统计学概念 3 模型评估与选择3.1 经验误差与过拟合3.2 评估方法3.2.1 留出法3.2.2 交叉验证法3.2.3 自助法3.2.4 调参与最终…

ssm060基于SSM的高校共享单车管理系统的设计与实现+vue(论文+源码)_kaic

设计题目&#xff1a;高校共享单车管理系统的设计与实现 摘 要 网络技术和计算机技术发展至今&#xff0c;已经拥有了深厚的理论基础&#xff0c;并在现实中进行了充分运用&#xff0c;尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代&#xff0…

聚观早报 | 比亚迪腾势D9登陆泰国;苹果 iOS 18.2 将发布

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 11月5日消息 比亚迪腾势D9登陆泰国 苹果 iOS 18.2 将发布 真我GT7 Pro防尘防水细节 小米15 Ultra最快明年登场 …

三菱QD77MS定位模块速度更改功能

速度更改功能” 是以任意时机将控制中的速度更改为新指定的速度的功能。更改后的速度直接设置到缓冲存储器中&#xff0c;并根据速度更改指令([cd.15速度更改请求)或者外部指令信号执行速度更改。 但是&#xff0c;机械原点复位的情况下&#xff0c;检测出近点狗 ON 并开始向蠕…

flink 内存配置(二):设置TaskManager内存

flink 内存配置&#xff08;一&#xff09;&#xff1a;设置Flink进程内存 flink 内存配置&#xff08;二&#xff09;&#xff1a;设置TaskManager内存 flink 内存配置&#xff08;三&#xff09;&#xff1a;设置JobManager内存 flink 内存配置&#xff08;四&#xff09;…

线段树专题(1)

线段树 线段树可维护的信息类型 线段树可以维护的信息类型&#xff0c;父范围上的某个信息&#xff0c;可以用O(1)的时间&#xff0c;从子范围的信息加工得到&#xff0c;例如求某个范围的最大最小值&#xff0c;给某个范围每个位置加相同的数字&#xff0c;进行求和。 0到2范…

NoETL自动化指标平台为数据分析提质增效,驱动业务决策

直觉判断往往来源于多年的经验和专业知识&#xff0c;能够在复杂和不确定的环境中快速做出决策反应。但这种方式普遍存在主观偏见&#xff0c;缺乏合理的科学依据&#xff0c;无法全面、客观、精准地评估和识别市场趋势与用户需求&#xff0c;从而造成决策失误&#xff0c;给业…

软考高级架构 - 8.1 - 系统质量属性与架构评估 - 超详细讲解+精简总结

第8章 系统质量属性与架构评估 软件系统属性包括功能属性和质量属性&#xff0c;而软件架构重点关注质量属性。 8.1 软件系统质量属性 8.1.1 概述 软件系统的质量反映了其与需求的一致性&#xff0c;即&#xff1a;软件系统的质量高低取决于它是否能满足用户提出的需求&#…

Jmeter常见的几种报错及解决方案

在性能测试的过程中&#xff0c;使用JMeter进行负载测试是一项常见而重要的任务。然而&#xff0c;测试中常常会遇到各种报错&#xff0c;这些问题可能会影响测试结果的准确性。了解这些错误的原因及解决方案&#xff0c;是每位测试工程师必备的技能 进行Jmeter项目练习的时候…

《JavaEE进阶》----21.<基于Spring图书管理系统②(图书列表+删除图书+更改图书)>

PS&#xff1a; 开闭原则 定义和背景‌ ‌开闭原则&#xff08;Open-Closed Principle, OCP&#xff09;‌&#xff0c;也称为开放封闭原则&#xff0c;是面向对象设计中的一个基本原则。该原则强调软件中的模块、类或函数应该对扩展开放&#xff0c;对修改封闭。这意味着一个软…

仿真APP助力汽车零部件厂商打造核心竞争力

汽车零部件是汽车工业的基石&#xff0c;是构成车辆的基础元素。一辆汽车通常由上万件零部件组成&#xff0c;包括发动机系统、传动系统、制动系统、电子控制系统等&#xff0c;它们共同确保了汽车的安全、可靠性及高效运行。 在汽车产业快速发展的今天&#xff0c;汽车零部件…

现代Web开发:Vue 3 组件化开发实战

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 现代Web开发&#xff1a;Vue 3 组件化开发实战 现代Web开发&#xff1a;Vue 3 组件化开发实战 现代Web开发&#xff1a;Vue 3 组…

Unity引擎智能座舱解决方案

作为全球领先的 3D 引擎之一&#xff0c;Unity引擎为车载3D HMI提供全栈支持。即为从概念设计到量产部署的整个 HMI 工作流程提供创意咨询、性能调优、项目开发等解决方案&#xff0c;从而为车载信息娱乐系统和智能驾驶座舱打造令人惊叹的交互式体验。 专为中国车企打造的HMI引…

MySQL必会知识精华6(组合WHERE子句)

我们的目标是&#xff1a;按照这一套资料学习下来&#xff0c;大家可以完成数据库增删改查的实际操作。同时轻松应对面试或者笔试题中MySQL相关题目。 上篇文章我们先做一下数据库的where条件过滤的方法&#xff0c;都是单个条件的过滤。本篇文章主要介绍查询的组合WHERE子句的…

[C++11] 可变参数模板

文章目录 基本语法及原理可变参数模板的基本语法参数包的两种类型可变参数模板的定义 sizeof... 运算符可变参数模板的实例化原理可变参数模板的意义 包扩展包扩展的基本概念包扩展的实现原理编译器如何展开参数包包扩展的高级应用 emplace 系列接口emplace_back 和 emplace 的…

欺诈文本分类检测(十八):基于llama.cpp+CPU推理

1. 前言 前文我们用Lora训练出自己的个性化模型后&#xff0c;首先面临的问题是&#xff1a;如何让模型在普通机器上跑起来&#xff1f;毕竟模型微调时都是在几十G的专用GPU上训练的&#xff0c;如果换到只有CPU的普通电脑上&#xff0c;可能会面临几秒蹦一个词的尴尬问题。 …

硬件基础06 滤波器——无源、有源(含Filter Solutions、Filter Pro、MATLAB Fdatool)

目录 一、Filter Solutions 1、软件资源及安装教程如下 2、使用相关内容 二、Filter Pro使用 1、软件资源及安装教程如下 2、使用相关内容 三、MATLAB Fdatool 1、在matlab命令中输入fdatool 2、输入相关参数&#xff0c;例如低通、FIR、20阶、hamming窗 3、调用 &am…

【HGT】文献精讲:Heterogeneous Graph Transformer

【HGT】文献精讲&#xff1a;Heterogeneous Graph Transformer 标题&#xff1a; Heterogeneous Graph Transformer &#xff08;异构图Transformer&#xff09; 作者团队&#xff1a; 加利福尼亚大学Yizhou Sun 摘要&#xff1a; 近年来&#xff0c;图神经网络&#xff08;GN…

大厂基本功 | MySQL 三大日志 ( binlog、redo log 和 undo log ) 的作用?

前言 MySQL日志 主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。其中&#xff0c;比较重要的还要属二进制日志binlog&#xff08;归档日志&#xff09;和事务日志redo log&#xff08;重做日志&#xff09;和undo log&#xff08;回滚日志&#xff09;…

【系统架构设计师(第2版)】五、软件工程基础知识

5.1 软件工程 20世纪60年代&#xff0c;为了解决软件危机&#xff0c;提出了软件工程的概念。 软件危机的具体表现&#xff1a; 软件开发进度难以预测&#xff1b;软件开发成本难以控制&#xff1b;软件功能难以满足用户期望&#xff1b;软件质量无法保证&#xff1b;软件难以…