查询from语句中的Outer Join可以在多种情况下被简化;

在解析阶段,右外连接操作可以被转变为等下ode值包含left join的操作,在一般情况下,转变:

(T1, ...) RIGHT JOIN (T2,...) ON P(T1,...,T2,...) =
(T2, ...) LEFT JOIN (T1,...) ON P(T1,...,T2,...)

所有inner join表达式形如(t1 inner join t2 on p(t1,t2))可以被(t1,t2,p(t1,t2))代替(通过where condition 做两表的conjunct或者嵌套连接条件 );

当优化器评估带有outer join操作的join 查询执行计划时,它只考虑这几种情况,外表在内表之前被访问;

e.g.

SELECT * T1 LEFT JOIN T2 ON P1(T1,T2)
WHERE P(T1,T2) AND R(T2)

where condition中的R(t2)减少了很多t2表中的匹配的行数,如果我们执行这条查询,优化器会毫不犹豫的先访问t1表,然后这将导致非常无效率的执行计划;

幸运的,如果where condition 为 null-rejected,Mysql 会把像这样的查询转变为非outer join操作。对于一个outer join操作,对于任何null被填充的行,如果null-rejected的condition判断为false或者unknown(即e.g. 对于left join,非left table,用Null值来填充行数据,当该条件可以判定该操作不成立);

e.g.

T1 LEFT JOIN T2 ON T1.A=T2.A

为null-rejected的条件有:

T2.B IS NOT NULL,
T2.B > 3,
T2.C <= T1.C,
T2.B < 2 OR T2.C > 1

为非null-rejected的条件:

T2.B IS NULL,
T1.B < 3 OR T2.B IS NOT NULL,
T1.B < 3 OR T2.B > 3

对Outer join操作的null-rejected条件常规条件比较简单:

1: 如果它是A is not null形式,当A 是任何内部表的一个属性;

2:如果一个连接包含一个null-rejected条件作为连接条件;

3:如果他是一个分裂的Null-rejected条件;

在一个outer join操作查询中, 一个Null-rejected条件,可能对于别的表为not null-rejected的:

SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A
LEFT JOIN T3 ON T3.B=T1.B
WHERE T3.C > 0

where条件对于第二个outer join操作是一个null-rejected条件,但是对于第一个就不是了。

如果where条件对于一个outer join操作是一个 null-rejected条件,那么该outer join操作可以转化为一个inner join操作;

SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A
INNER JOIN T3 ON T3.B=T1.B
WHERE T3.C > 0

对于原始的查询,优化器会苹果查询计划通过唯一的访问顺序t1,t2,t3,对于上述的替代查询,他可能会考虑t3,t1,t2

一个outer join操作的转变可能触发另外一个的转变:

SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A
LEFT JOIN T3 ON T3.B=T2.B
WHERE T3.C > 0

first:

SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A
INNER JOIN T3 ON T3.B=T2.B
WHERE T3.C > 0

等效于:

SELECT * FROM (T1 LEFT JOIN T2 ON T2.A=T1.A), T3
WHERE T3.C > 0 AND T3.B=T2.B

现在剩余的outer join操作可以被替换成一个inner join,因为条件t3.b= t2.b是一个null-rejected,所以我们得到一个没有outer join的查询

SELECT * FROM (T1 INNER JOIN T2 ON T2.A=T1.A), T3
WHERE T3.C > 0 AND T3.B=T2.B

有时我们可以替换一个嵌套的outer join操作,但不是不能转变嵌套outer join;

SELECT * FROM T1 LEFT JOIN
(T2 LEFT JOIN T3 ON T3.B=T2.B)
ON T2.A=T1.A
WHERE T3.C > 0

替换为:

SELECT * FROM T1 LEFT JOIN
(T2 INNER JOIN T3 ON T3.B=T2.B)
ON T2.A=T1.A
WHERE T3.C > 0,

可以被重写成依旧包含嵌套outer join操作:

SELECT * FROM T1 LEFT JOIN
(T2,T3)
ON (T2.A=T1.A AND T3.B=T2.B)
WHERE T3.C > 0.

当尝试转变一个嵌套outer join操作是,必须把嵌套的outer join的join condition和where 条件一起考虑:

SELECT * FROM T1 LEFT JOIN
(T2 LEFT JOIN T3 ON T3.B=T2.B)
ON T2.A=T1.A AND T3.C=T1.C
WHERE T3.D > 0 OR T1.D > 0

where条件不是嵌套outer join的一个null-rejected条件,但嵌套outer join的连接条件T2.A=T1.A AND T3.C=T1.C 是一个null-rejected条件,所以等效与:

SELECT * FROM T1 LEFT JOIN
(T2, T3)
ON T2.A=T1.A AND T3.C=T1.C AND T3.B=T2.B
WHERE T3.D > 0 OR T1.D > 0

MySql Outer Join 简单化的更多相关文章

  1. mysql inner join,full outer join,left join,right jion

    https://sites.google.com/site/349624yu/courses/mysql/mysqldbgjzcx inner join,full outer join,left jo ...

  2. MySQL实现全关联 full outer join

    SQL LEFT JOIN 关键字 LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行. LEFT JOIN 关键 ...

  3. mysql实现full outer join

    由于MySQL设计时不支持full outer join, 所以如果有全连接需求时,需要一点小技巧来实现. 假设有两个表t1,t2 full outer join 的效果和下面的效果一样: SELEC ...

  4. Mysql 多表连接查询 inner join 和 outer join 的使用

    JOIN的含义就如英文单词“join”一样,连接两张表,大致分为内连接,外连接,右连接,左连接,自然连接.这里描述先甩出一张用烂了的图,然后插入测试数据. 首先先列举本篇用到的分类(内连接,外连接,交 ...

  5. MySQL中没有FULL OUTER JOIN的处理

    FULL OUTER JOIN:SELECT column_name(s)FROM table1FULL OUTER JOIN table2ON table1.column_name=table2.c ...

  6. mysql的left jion:就是left outer join(right join同理)

    左外连接: A left jion B on A.id=B.id 就是A表数据不动,将B表里面能和A对应上的数据补充到A表数据后 而右外连接: rignt jion 则是将A补充到B,B不动,保存全部 ...

  7. Mysql: 图解 inner join、left join、right join、full outer join、union、union all的区别

    转载来源 对于SQL的Join,在学习起来可能是比较乱的.我们知道,SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚. ...

  8. MySQL Left Join,Right Join

    魂屁,东西发这里了关于Left Join,Right Join的 在讲MySQL的Join语法前还是先回顾一下联结的语法,呵呵,其实连我自己都忘得差不多了,那就大家一起温习吧(如果内容有错误或有疑问, ...

  9. MySQL的JOIN(一):用法

    JOIN的含义就如英文单词"join"一样,连接两张表,大致分为内连接,外连接,右连接,左连接,自然连接.这里描述先甩出一张用烂了的图,然后插入测试数据. CREATE TABLE ...

随机推荐

  1. volatile关键字的特性总结

    当一个变量定义为volatile后,它将具备两个特性: 1.保证此变量对所有线程的可见性,所谓"可见性",,是指当一个线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的. ...

  2. Spring之Bean的基本概念

     转自http://blog.csdn.net/chenssy/article/details/8222744 Spring其实就是一个大型的工厂,而Spring容器中的Bean就是该工厂的产品.对于 ...

  3. Java学习笔记-枚举类型

    枚举类型 枚举类型就是预先定义的一类常量集合,如一周的时间.水果的类型等.需要注意的几点内容如下: 定义枚举类时,Java默认继承java.lang.Enum,所以定义的枚举类不能继承其他类型: 枚举 ...

  4. JS输出26个英文大小写字母

    JS中可以利用ASCII值 for(var i=0;i<26;i++){ console.log(String.fromCharCode(65+i));//输出A-Z 26个大写字母 } for ...

  5. 【CSS初识】

    一.CSS是什么? CSS是一种样式表语言,用于为HTML文档定义布局.例如,CSS涉及字体.颜色.边距.高度.宽度.背景图像.高级定位等方面. HTML用于结构化内容:CSS用于格式化结构化的内容. ...

  6. Android-AnsyncTask异步任务

    同步和异步的概念区别: 同步,必须执行完成某个问题后才能继续执行其他的. 异步,我会去先执行其他问题,你执行完之后返回给我一个结果就可以. android中为什么要引用异步任务呢 android启动的 ...

  7. MySQL两阶段提交

    参数介绍 innodb_flush_log_at_trx_commit 0: 每隔1s,系统后台线程刷log buffer,也就是把redo日志刷盘,这里会调用fsync,所以可能丢失最后1s的事务. ...

  8. flask-日料网站搭建

    引言:想使用python的flask框架搭建一个日料网站,主要包含web架构,静态页面,后台系统,交互. 本节知识:搭建web目录,目前正在copy网站. python环境:python2.7,fla ...

  9. oracle如何导出和导入数据库表

    oracle如何导出和导入数据库表 oracle如何将项目中的表导出后在导入自己的数据库中,这是一个完整的操作,对于数据库备份或在本地查看数据验证数据进场用到,一般情况下我都用dos黑窗口进行操作,简 ...

  10. 移动端吸顶(iOS与安卓)

    有的时候经常会遇到移动端吸顶效果,开始我也只是上网查了一下,分别有iOS和android两种样式,如下: /*!*Android*!*/ .head { position: fixed; top: 0 ...