Inner Join与Left Join
Inner Join与Left Join
内连接、外连接、半连接区别是什么?
先创建一个示例表及数据:
postgres=# create table t10(id1 int,id2 int);
CREATE TABLE
postgres=# create table t11(id1 int,id2 int);
CREATE TABLE
postgres=# select * from t11;id1 | id2
-----+-----2 | 45 | 63 | 5
(3 行记录)postgres=# select * from t10;id1 | id2
-----+-----1 | 22 | 33 | 4
(3 行记录)
示例很简单,下面做下演示。
隐式连接与显式连接
先看隐式连接:
postgres=# select * from t10,t11 where t10.id1=t11.id1;id1 | id2 | id1 | id2
-----+-----+-----+-----2 | 3 | 2 | 43 | 4 | 3 | 5
(2 行记录)
这种情况下,连接实际发生在WHERE子句中。在FROM子句中,只需要列出JOIN的表。另一种显式连接:
postgres=# select * from t10 join t11 on t10.id1=t11.id1;id1 | id2 | id1 | id2
-----+-----+-----+-----2 | 3 | 2 | 43 | 4 | 3 | 5
(2 行记录)
两者的语法其实是一致的,看下他们的执行计划就可以知道,他们的执行计划完全一样:
postgres=# explain select * from t10,t11 where t10.id1=t11.id1;QUERY PLAN
-------------------------------------------------------------------Merge Join (cost=317.01..711.38 rows=25538 width=16)Merge Cond: (t10.id1 = t11.id1)-> Sort (cost=158.51..164.16 rows=2260 width=8)Sort Key: t10.id1-> Seq Scan on t10 (cost=0.00..32.60 rows=2260 width=8)-> Sort (cost=158.51..164.16 rows=2260 width=8)Sort Key: t11.id1-> Seq Scan on t11 (cost=0.00..32.60 rows=2260 width=8)
(8 行记录)postgres=# explain select * from t10 join t11 on t10.id1=t11.id1;QUERY PLAN
-------------------------------------------------------------------Merge Join (cost=317.01..711.38 rows=25538 width=16)Merge Cond: (t10.id1 = t11.id1)-> Sort (cost=158.51..164.16 rows=2260 width=8)Sort Key: t10.id1-> Seq Scan on t10 (cost=0.00..32.60 rows=2260 width=8)-> Sort (cost=158.51..164.16 rows=2260 width=8)Sort Key: t11.id1-> Seq Scan on t11 (cost=0.00..32.60 rows=2260 width=8)
(8 行记录)
对于MOST查询来说,优化器基本上以相同的方式处理这两个查询。如果您碰巧运行一个典型的应用程序,则没有区别。但是有一些细微的差异需要提一下。我们看个变量:
postgres=# show join_collapse_limit;
join_collapse_limit
---------------------
8
(1 行记录)
这个参数的意义:每当生成的 items 列表不超过本参数值时,planner 就会将 explicit join 结构(FULL JOINs 除外)重写为 FROM items 列表。较小的值会减少计划时间,但可能会产生较差的查询计划。默认情况下,此参数值设置为与 from_collapse_limit 参数值相同,这适用于大多数用途。将其设置为 1 可防止 explicit join 的任何重新排序。因此,查询中指定的显式连接顺序将是连接关系的实际顺序。因为查询规划器并不总是选择最佳的连接顺序,所以高级用户可以选择将此参数值临时设置为 1,然后显式指定所需的连接顺序。设置本参数值为 geqo_threshold 参数值或者更大可能会触发 GEQO Planner 的使用,进而导致非优化的执行计划。
大多数情况下,显式和隐式JOIN是风格问题,而不是性能问题。但,在真正复杂的查询时确实存在差异。
INNER JOIN与OUTER JOIN
内连接在JOIN表中查找公共元组,外连接始终获取一侧的所有数据并在另一侧找相应的匹配项:
postgres=# select * from t10 left join t11 on t10.id1=t11.id1;id1 | id2 | id1 | id2
-----+-----+-----+-----1 | 2 | |2 | 3 | 2 | 43 | 4 | 3 | 5
(3 行记录)
这里是t10作为left表,并在右侧找匹配的行。与left join相反的是右连接:
postgres=# select * from t10 right join t11 on t10.id1=t11.id1;id1 | id2 | id1 | id2
-----+-----+-----+-----2 | 3 | 2 | 43 | 4 | 3 | 5| | 5 | 6
(3 行记录)
全连接
还有一种连接--全连接。他的作用是从双方获取所有数据并找匹配项。没有匹配的在对应一侧填充NULL:
postgres=# select * from t10 full join t11 on t10.id1=t11.id1;id1 | id2 | id1 | id2
-----+-----+-----+-----1 | 2 | |2 | 3 | 2 | 43 | 4 | 3 | 5| | 5 | 6
(4 行记录)
虽然编码相对容易,但是由于对外连接的作用存在误解,人们常会犯错误。
外连接常见错误
比如在连接条件中加了个AND子句:
postgres=# select * from t10 left join t11 on t10.id1=t11.id1 and t11.id1=2;id1 | id2 | id1 | id2
-----+-----+-----+-----1 | 2 | |2 | 3 | 2 | 43 | 4 | |
(3 行记录)
大多数人实际期望结果集比以前小,但事实并非如此。ON条件仅改变了匹配的行,一个LEFT JOIN仍会在左侧产生所有行。附件条件只是将一些条目更高为NULL,他会不减少数据量。
postgres=# select * from t10 left join t11 on t10.id1=t11.id1 ;
id1 | id2 | id1 | id2
-----+-----+-----+-----
1 | 2 | |
2 | 3 | 2 | 4
3 | 4 | 3 | 5
(3 行记录)
涉及聚集时,很容易隐藏潜在的语义问题:
postgres=# select count(*),count(t11.id1) from t10 left join t11 on t10.id1=t11.id1 and t11.id1=2;
count | count
-------+-------
3 | 1
(1 行记录)
IN:Semi Join
什么是半连接?思考下IN语句:
postgres=# select * from t10 where id1 in(select id1 from t11);
id1 | id2
-----+-----
2 | 3
3 | 4
(2 行记录)
IN语句是一个隐式的DISTINCT过滤器,用于删除重复的条目。因此连接与半连接的区别在于处理重复项的方式。
执行计划清楚的显示这些重复项已被删除。这种情况下,使用HashAggregate完成。(许多情况下,还会在GROUP BY语句中看到):
postgres=# explain select * from t10 where id1 in(select id1 from t11);QUERY PLAN
-------------------------------------------------------------------------Hash Join (cost=42.75..93.85 rows=1130 width=8)Hash Cond: (t10.id1 = t11.id1)-> Seq Scan on t10 (cost=0.00..32.60 rows=2260 width=8)-> Hash (cost=40.25..40.25 rows=200 width=4)-> HashAggregate (cost=38.25..40.25 rows=200 width=4)Group Key: t11.id1-> Seq Scan on t11 (cost=0.00..32.60 rows=2260 width=4)
(7 行记录)
IN语句的反义词是NOT IN:
postgres=# select * from t10 where id1 not in(select id1 from t11);
id1 | id2
-----+-----
1 | 2
(1 行记录)
这种情况下,从结果集中删除其他行。
Inner Join与Left Join相关推荐
- sql语句中left join和inner join中的on与where的区别分析
原文:sql语句中left join和inner join中的on与where的区别分析 关于SQL SERVER的表联接查询INNER JOIN .LEFT JOIN和RIGHT JOIN,经常会用 ...
- SQL的连接(join)有哪些常见形式?解释一下?解释 SQL 的 left join 和 right join?
SQL的连接(join)有哪些常见形式?解释一下?解释 SQL 的 left join 和 right join? SQL的连接(join)有哪些常见形式? sql连接查询:把多张表的列组合在一起,产 ...
- sql之left join、right join、inner join的区别,连接自己时的查询结果测试
sql之left join.right join.inner join的区别 left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包 ...
- mysql的left join和inner join的效率对比,以及如何优化
一.前言 最近在写代码的时候,遇到了需要多表连接的一个问题,初始sql类似于: select * from a left join b on a.x = b.x left join c on c.y ...
- SQL性能--left join和inner join的运行速度与效率
①大家都知道,sql尽量使用数据量小的表做主表,这样效率高,如果使用数据量大的表做主表,此时使用left join 就会比较慢,即使关联条件有索引.但如果使用inner join速度就较快.因为inn ...
- Database之SQLSever:SQL命令实现查询之多表查询、嵌套查询、分页复杂查询,删除表内重复记录数据、连接(join、left join和right join简介及其区别)等案例之详细攻略
Database之SQLSever:SQL命令实现查询之多表查询.嵌套查询.分页复杂查询,删除表内重复记录数据.连接(join.left join和right join简介及其区别)等案例之详细攻略 ...
- Access SQL中Left Join、Right Join和Inner Join的使用
1.表结构 表A 表B 2.Left Join 示例:2.1 Select * From A left join B on A. ...
- oracle join详解,inner join和left join之间的区别详解
前言 关于inner join 与 left join 之间的区别,以前以为自己搞懂了,今天从前端取参数的时候发现不是预想中的结果,才知道问题出在inner join 上了. 需求是从数据库查数据,在 ...
- Mysql 优化器内部JOIN算法hash join On-Disk Hash Join Grace Hash Join Hybrid hash join过程详解
Mysql 各种hash join算法讲解 hash join的概述 提到hash join之前自然得说Nest loop join,以两个表的关联为例,它其实是个双层循环,先遍历外层的表(n条),再 ...
- Mysql 优化器内部JOIN算法hash join Nestloopjoin及classic hash join CHJ过程详解
Mysql hash join之classic hash join CHJ过程详解 hash join的历史 优化器里的hash join算法在SQL Server.Oracle.postgress等 ...
最新文章
- 动态规划-最优二叉查找树
- 【EntityFramework系列教程三,翻译】在ASP.NET MVC程序中使用EntityFramework对数据进行排序、过滤筛选以及实现分页...
- matlab撤销上一步命令_CAD快速入门技巧:CAD软件中撤销操作的方法汇总
- C语言 | 编程实现1
- Spark DataFrame小试牛刀
- eclipse优化运行速度_IPFS:强化公共DHT以抵抗eclipse攻击
- python快速编程入门课本中的名片管理器_Python-名片管理器
- windsns社交门户系统源码v1.0-掌上移动社交类SNS网站系统源码
- 秦时明月1架设用哪个java_秦时明月6.2搭建视频架设教程
- Abaqus槽钢杆受力有限元分析
- 老年人计算机培训信息,老年人学习电脑基础知识
- ListView数据动态刷新
- 华为hcie认证工程师里一定要知道的Radius 基本介绍
- 聊天框体实现:好友填充框
- oracle数据库创建Sequence序列
- 跨境智星自养号系统功能介绍与操作说明
- 电脑摄像头阅卷软件在教学各环节中的实践应用
- 博彦科技面试—20190802—周五 14:00
- 反编译及手机平板apk提取
- 华硕ezflash3找不到u盘_请问华硕主板的BIOS用EZ FLASH 2怎么更新?我把下载的BIOS放在硬盘上...