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相关推荐

  1. sql语句中left join和inner join中的on与where的区别分析

    原文:sql语句中left join和inner join中的on与where的区别分析 关于SQL SERVER的表联接查询INNER JOIN .LEFT JOIN和RIGHT JOIN,经常会用 ...

  2. SQL的连接(join)有哪些常见形式?解释一下?解释 SQL 的 left join 和 right join?

    SQL的连接(join)有哪些常见形式?解释一下?解释 SQL 的 left join 和 right join? SQL的连接(join)有哪些常见形式? sql连接查询:把多张表的列组合在一起,产 ...

  3. sql之left join、right join、inner join的区别,连接自己时的查询结果测试

    sql之left join.right join.inner join的区别 left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录  right join(右联接) 返回包 ...

  4. mysql的left join和inner join的效率对比,以及如何优化

    一.前言 最近在写代码的时候,遇到了需要多表连接的一个问题,初始sql类似于: select * from a left join b on a.x = b.x left join c on c.y ...

  5. SQL性能--left join和inner join的运行速度与效率

    ①大家都知道,sql尽量使用数据量小的表做主表,这样效率高,如果使用数据量大的表做主表,此时使用left join 就会比较慢,即使关联条件有索引.但如果使用inner join速度就较快.因为inn ...

  6. Database之SQLSever:SQL命令实现查询之多表查询、嵌套查询、分页复杂查询,删除表内重复记录数据、连接(join、left join和right join简介及其区别)等案例之详细攻略

    Database之SQLSever:SQL命令实现查询之多表查询.嵌套查询.分页复杂查询,删除表内重复记录数据.连接(join.left join和right join简介及其区别)等案例之详细攻略 ...

  7. Access SQL中Left Join、Right Join和Inner Join的使用

    1.表结构 表A                                     表B 2.Left Join 示例:2.1 Select * From A left join B on A. ...

  8. oracle join详解,inner join和left join之间的区别详解

    前言 关于inner join 与 left join 之间的区别,以前以为自己搞懂了,今天从前端取参数的时候发现不是预想中的结果,才知道问题出在inner join 上了. 需求是从数据库查数据,在 ...

  9. 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条),再 ...

  10. Mysql 优化器内部JOIN算法hash join Nestloopjoin及classic hash join CHJ过程详解

    Mysql hash join之classic hash join CHJ过程详解 hash join的历史 优化器里的hash join算法在SQL Server.Oracle.postgress等 ...

最新文章

  1. 动态规划-最优二叉查找树
  2. 【EntityFramework系列教程三,翻译】在ASP.NET MVC程序中使用EntityFramework对数据进行排序、过滤筛选以及实现分页...
  3. matlab撤销上一步命令_CAD快速入门技巧:CAD软件中撤销操作的方法汇总
  4. C语言 | 编程实现1
  5. Spark DataFrame小试牛刀
  6. eclipse优化运行速度_IPFS:强化公共DHT以抵抗eclipse攻击
  7. python快速编程入门课本中的名片管理器_Python-名片管理器
  8. windsns社交门户系统源码v1.0-掌上移动社交类SNS网站系统源码
  9. 秦时明月1架设用哪个java_秦时明月6.2搭建视频架设教程
  10. Abaqus槽钢杆受力有限元分析
  11. 老年人计算机培训信息,老年人学习电脑基础知识
  12. ListView数据动态刷新
  13. 华为hcie认证工程师里一定要知道的Radius 基本介绍
  14. 聊天框体实现:好友填充框
  15. oracle数据库创建Sequence序列
  16. 跨境智星自养号系统功能介绍与操作说明
  17. 电脑摄像头阅卷软件在教学各环节中的实践应用
  18. 博彦科技面试—20190802—周五 14:00
  19. 反编译及手机平板apk提取
  20. 华硕ezflash3找不到u盘_请问华硕主板的BIOS用EZ FLASH 2怎么更新?我把下载的BIOS放在硬盘上...

热门文章

  1. 宝塔面板安装docker 再到docker容器里面安装宝塔
  2. python中列表概念_详解python列表
  3. mysql主从复制,互为主从与读写分离
  4. JavaScript里的var变量
  5. 2008nian元旦
  6. B站服务端代码泄漏:如何提交takedown,删除泄漏源码的仓库和Fork
  7. Java打破双亲委派机制
  8. Emacs学习使用之路(一)
  9. 爱死Intellij Idea 01
  10. 读入一幅图像,对图像分别进行高斯低通、巴特沃兹低通、高斯高通和巴特沃兹高通频域滤波,比较其锐化和平滑效果。