查询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. HY.Mail:C#简单、易用的邮件工具库

    一.开发HY.Mail的初衷 Nuget或者github上有很多成熟且优秀的邮件库可以使用, 但是目前找到的使用都不够简洁或者不适合我的使用场景 我的场景是开发应用场景(例如系统通知.运维通知),而非 ...

  2. java多线程(一)-概述

    最近这段在看java多线程编程方面的东西.所以特写了几篇文章,来总结和回顾一下自己所学习到的相关知识.因为水平有限,文章中总结不全面甚至理解错误的地方,欢迎读者指点批评. 我们平时所接触到的程序,都是 ...

  3. IntelliJ IDEA2017.3 激活

    网上IntelliJ IDEA激活方式大多均已失效,目前常用激活方式为License Server 激活: http://idea.imsxm.com/ NOTE: 在上周五2017-12-1那天还是 ...

  4. HTML5新特性:元素的classList属性与应用

    在html5新增的classList之前, 操作元素的class用的是className这个属性,而如果要向jquery封装的hasClass, removeClass, addClass, togg ...

  5. Qt实现QQ界面

    1.Qt实现QQ界面是通过QToolBox类来实现的,基本结构是:QToolBox里面装QGroupBox,然后QGroupBox里面装QToolButton,设置好相关属性即可 2.定义类继承QTo ...

  6. eclipse启动tomcat不能访问解决

    tomcat在eclipse里面能正常启动,而在浏览器中访问http://localhost:8080/不能访问,且报404错误.同时其他项目页面也不能访问. 关闭eclipse里面的tomcat,在 ...

  7. 企业级memcached缓存数据库结合php使用与web管理memcached

    环境 [root@cache01 ~]# cat /etc/redhat-release CentOS Linux release (Core) [root@cache01 ~]# uname -a ...

  8. grpc 入门(一)--hello world

    一,从rpc接口的定义说起,下面给一个最简单的grpc示例--hello world 在这个rpc横行的世界里,实现一个rpc很重要的一件事就是定义一个好接口,一个好的接口定义会让你省去很多麻烦.熟悉 ...

  9. 大话python模块与包

    前言 眼看着老掌门年纪越来越大,掌门之位的传承也成了门派中的一件大事.这天,老掌门把小掌门叫到跟前,语重心长地说道:孩子啊,以后你就要继任掌门之位了,我就传授此生所学的绝世功法与你,以后可要悉心学习, ...

  10. H5+Ajax+WebApi实现文件下载(进度条,多文件)

    前言 踩过的坑 1.WebAPI跨域 2.Jquery ajax低版本不支持XHR 2功能 3.Jquery ajax不支持Deferred的process事件 4.IE下文件名乱码问题 功能实现 & ...