查询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. Windows 7样式地址栏(Address Bar)控件实现

    介绍 从Vista开始,地址栏就有了很大的改变,不知道大家有什么感觉,笔者觉得很方便,同时又兼容之前的功能,是个很不错的创新.不过,微软并不打算把这一很酷的功能提供给广大的开发人员. 本文提供了一个简 ...

  2. 一个超级简单的demo带你走进redux的大坑

    先上代码 import React, { Component } from 'react'; import ReactDOM from 'react-dom'; import { createStor ...

  3. vue2.0 页面A跳转到页面B,B页面停留在A页面的滚动位置的解决方法

    如果页面A沿Y轴滚动一段距离,然后跳转到页面B: 在进入B页面时,B页面已经滚到页面A的距离,返回页面A,发现A还在之前的滚动位置: 这样体验就很不好,所以我们要进行一些处理: 我的方法是:在路由守卫 ...

  4. 第十二章:Python の 网络编程进阶(一)

    本課主題 RabbitMQ 的介紹和操作 Hello RabbitMQ RabbitMQ 的工作队列 消息确应.消息持久化和公平调度模式 RabbitMQ的发布和订阅 RabbitMQ的主题模式 Ra ...

  5. eclipse常用快捷设置

    1.代码自动提示 在我们忘记方法名或者想偷懒时,代码自动提示很管用.不过Eclipse默认是输入"."后才会出现包或类成员的提示,也就意味着我们必须先输入一个完整的类名,提示才能出 ...

  6. Android 中log 找到关键log

    SYS_ANDROID_EVENT_LOG1. aee_exp文件夹中有 db.fatal.00.SWT. 2. 准备工作: gat打开db.fatal.00.SWT.dbg文件,即会生成.DEC文件 ...

  7. centos下卸载OpenJDK 并安装sun的jdk

    centos下卸载OpenJDK 并安装sun的jdk 第一步:查看并卸载CentOS自带的OpenJDK 安装好的CentOS会自带OpenJdk,用命令 java -version ,我这里显示下 ...

  8. 高效开发技巧:为什么你下载Git项目这么慢?

    文章首发于[博客园-陈树义],点击跳转到原文<高效开发技巧:为什么你下载Git项目这么慢?>. 笔者所在公司采用的是 GitLab 进行版本管理,但许多同事下载 Git 项目的路径是这样的 ...

  9. 微信小程序之获取验证码js

    在微信小程序中怎样实现获取验证码的倒计时功能捏,倒计时的原理是一样一样的,就是某些地方需要注意. 第一步:结构 <view class='get-code' wx:if="{{!isS ...

  10. conda虚拟环境实践

    1.查看本地创建了那些python版本 which python whereis python which主要用来查找可直接执行的命令,可以查找别名.whereis比which的搜索范围大了一些,同时 ...