外连接转换为内连接的情况

简介: 一般的情况下外连接如下a right join b on a.id=b.id 那么b一定要作为驱动表,原因在于只有b作为驱动表才能得到完整的结果集,如果a作为驱动,那么返回的结果集 可能不完整,但是在特殊的情况的,可能将外连接转换为内连接 考虑如下的情况 b  ...
一般的情况下外连接如下a right join b on a.id=b.id 那么b一定要作为驱动表,原因在于只有b作为驱动表才能得到完整的结果集,如果a作为驱动,那么返回的结果集
可能不完整,但是在特殊的情况的,可能将外连接转换为内连接
考虑如下的情况


  id  name
  1   g1
  1   g2
  2   g3
  2   g4

a
  id name
  2  gname2

使用如下语句:
select b.id,a.id from 
a right join b on a.id=b.id 
where a.id=2;

先不考虑where a.id=1;
做外连接返回的值应该为
b.id a.id
1     null
1     null
2     2
2     2

现在来考虑a.id =2 ;
那么如果这样过滤那么结果集合如下:

b.id a.id
2     2
2     2

这正是内连接的得到的结果集,也就是说只要a.id 限定为一定固定的非空的值,内连接出来的结构集就能
完全的满足谓词条件过滤后得到结果的全部中间结果集,那么数据库将会进行转换。MYSQL ORACLE都是如此

mysql:
mysql> explain select b.id,a.id from  a right join b on a.id=b.id  where a.id =2;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                                              |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------------------------------------------+
|  1 | SIMPLE      | a     | ALL  | NULL          | NULL | NULL    | NULL |    2 | Using where                                        |
|  1 | SIMPLE      | b     | ALL  | NULL          | NULL | NULL    | NULL |    4 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------------------------------------------+
2 rows in set (0.00 sec)
a作为了驱动表
oracle:

SQL> select b.id from a right join b on a.id=b.id  where a.id=2;

Execution Plan
----------------------------------------------------------
Plan hash value: 652036164
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |    26 |     5  (20)| 00:00:01 |
|*  1 |  HASH JOIN         |      |     1 |    26 |     5  (20)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL| A    |     1 |    13 |     2   (0)| 00:00:01 |
|*  3 |   TABLE ACCESS FULL| B    |     2 |    26 |     2   (0)| 00:00:01 |


可以看到本该出现的 HASH JOIN OUTER 没有出现。

但是如果将条件where a.id=2;改为where a.id is null;那么显然这种转换不合理,因为
内连接出来的结果集已经不能满足 a.id is null;的要求。

为什么要这样转换,我们知道在做连接的时候不管是NEST LOOP和HASN JOIN都应该把小表
作为驱动表,效率一般更高,那么外连接限定死了顺序可能大表做为驱动表,那么效率
显然更低,如果做了内连接的转换那么选择的顺序就更多,效率可能得到提高,当然
这和统计数据的精准度有很大的关系。

相关文章
|
6月前
|
关系型数据库 MySQL 数据库
MySQL数据库——多表查询(2)-内连接、外连接
MySQL数据库——多表查询(2)-内连接、外连接
49 1
|
关系型数据库 MySQL 数据库
MySQL查询之 连接查询 - 内连接 左连接 右连接以及全连接
MySQL查询之 连接查询 - 内连接 左连接 右连接以及全连接
139 0
|
关系型数据库 MySQL 数据库
mysql 内连接、左连接(左外连接)、右连接(右外连接)、全连接(全外连接)
mysql 内连接、左连接(左外连接)、右连接(右外连接)、全连接(全外连接)
234 0
mysql 内连接、左连接(左外连接)、右连接(右外连接)、全连接(全外连接)
内连接、左外连接、右外连接、全外连接区别
内连接、左外连接、右外连接、全外连接区别
内连接、左外连接、右外连接、全外连接区别
|
关系型数据库 MySQL
一文完整MySQL连接查询,笛卡尔乘积,内连接外连接交叉连接
一文完整MySQL连接查询,笛卡尔乘积,内连接外连接交叉连接
209 0
一文完整MySQL连接查询,笛卡尔乘积,内连接外连接交叉连接
|
SQL 关系型数据库 MySQL
SQL内连接、外连接、全连接、交叉连接、自连接、自然连接区别
本文是博主学习SQL的记录,希望对大家有所帮助
1153 0
SQL内连接、外连接、全连接、交叉连接、自连接、自然连接区别
|
存储 关系型数据库 MySQL
mysql加强(4)~多表查询:笛卡尔积、消除笛卡尔积操作(等值、非等值连接),内连接(隐式连接、显示连接)、外连接、自连接
mysql加强(4)~多表查询:笛卡尔积、消除笛卡尔积操作(等值、非等值连接),内连接(隐式连接、显示连接)、外连接、自连接
910 0
mysql加强(4)~多表查询:笛卡尔积、消除笛卡尔积操作(等值、非等值连接),内连接(隐式连接、显示连接)、外连接、自连接
用图表示 内连接 左外连接右外连接的区别
用图表示 内连接 左外连接右外连接的区别
119 0
用图表示 内连接 左外连接右外连接的区别
|
SQL 数据库
使用 DML语句,对 “锦图网” 数据进行操作,连接查询(内连接,左外连接,右外连接,全连接)
使用 DML语句,对 “锦图网” 数据进行操作,连接查询(内连接,左外连接,右外连接,全连接)
110 0
|
SQL Oracle 关系型数据库
深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接
深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接1、内联接(典型的联接运算,使用像 = 或 <> 之类的比较运算符)。包括相等联接和自然联接。 内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行。
2347 0