MySql Outer Join 简单化
查询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 简单化的更多相关文章
- 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 ...
- MySQL实现全关联 full outer join
SQL LEFT JOIN 关键字 LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行. LEFT JOIN 关键 ...
- mysql实现full outer join
由于MySQL设计时不支持full outer join, 所以如果有全连接需求时,需要一点小技巧来实现. 假设有两个表t1,t2 full outer join 的效果和下面的效果一样: SELEC ...
- Mysql 多表连接查询 inner join 和 outer join 的使用
JOIN的含义就如英文单词“join”一样,连接两张表,大致分为内连接,外连接,右连接,左连接,自然连接.这里描述先甩出一张用烂了的图,然后插入测试数据. 首先先列举本篇用到的分类(内连接,外连接,交 ...
- MySQL中没有FULL OUTER JOIN的处理
FULL OUTER JOIN:SELECT column_name(s)FROM table1FULL OUTER JOIN table2ON table1.column_name=table2.c ...
- 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不动,保存全部 ...
- Mysql: 图解 inner join、left join、right join、full outer join、union、union all的区别
转载来源 对于SQL的Join,在学习起来可能是比较乱的.我们知道,SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚. ...
- MySQL Left Join,Right Join
魂屁,东西发这里了关于Left Join,Right Join的 在讲MySQL的Join语法前还是先回顾一下联结的语法,呵呵,其实连我自己都忘得差不多了,那就大家一起温习吧(如果内容有错误或有疑问, ...
- MySQL的JOIN(一):用法
JOIN的含义就如英文单词"join"一样,连接两张表,大致分为内连接,外连接,右连接,左连接,自然连接.这里描述先甩出一张用烂了的图,然后插入测试数据. CREATE TABLE ...
随机推荐
- Windows 7样式地址栏(Address Bar)控件实现
介绍 从Vista开始,地址栏就有了很大的改变,不知道大家有什么感觉,笔者觉得很方便,同时又兼容之前的功能,是个很不错的创新.不过,微软并不打算把这一很酷的功能提供给广大的开发人员. 本文提供了一个简 ...
- 一个超级简单的demo带你走进redux的大坑
先上代码 import React, { Component } from 'react'; import ReactDOM from 'react-dom'; import { createStor ...
- vue2.0 页面A跳转到页面B,B页面停留在A页面的滚动位置的解决方法
如果页面A沿Y轴滚动一段距离,然后跳转到页面B: 在进入B页面时,B页面已经滚到页面A的距离,返回页面A,发现A还在之前的滚动位置: 这样体验就很不好,所以我们要进行一些处理: 我的方法是:在路由守卫 ...
- 第十二章:Python の 网络编程进阶(一)
本課主題 RabbitMQ 的介紹和操作 Hello RabbitMQ RabbitMQ 的工作队列 消息确应.消息持久化和公平调度模式 RabbitMQ的发布和订阅 RabbitMQ的主题模式 Ra ...
- eclipse常用快捷设置
1.代码自动提示 在我们忘记方法名或者想偷懒时,代码自动提示很管用.不过Eclipse默认是输入"."后才会出现包或类成员的提示,也就意味着我们必须先输入一个完整的类名,提示才能出 ...
- Android 中log 找到关键log
SYS_ANDROID_EVENT_LOG1. aee_exp文件夹中有 db.fatal.00.SWT. 2. 准备工作: gat打开db.fatal.00.SWT.dbg文件,即会生成.DEC文件 ...
- centos下卸载OpenJDK 并安装sun的jdk
centos下卸载OpenJDK 并安装sun的jdk 第一步:查看并卸载CentOS自带的OpenJDK 安装好的CentOS会自带OpenJdk,用命令 java -version ,我这里显示下 ...
- 高效开发技巧:为什么你下载Git项目这么慢?
文章首发于[博客园-陈树义],点击跳转到原文<高效开发技巧:为什么你下载Git项目这么慢?>. 笔者所在公司采用的是 GitLab 进行版本管理,但许多同事下载 Git 项目的路径是这样的 ...
- 微信小程序之获取验证码js
在微信小程序中怎样实现获取验证码的倒计时功能捏,倒计时的原理是一样一样的,就是某些地方需要注意. 第一步:结构 <view class='get-code' wx:if="{{!isS ...
- conda虚拟环境实践
1.查看本地创建了那些python版本 which python whereis python which主要用来查找可直接执行的命令,可以查找别名.whereis比which的搜索范围大了一些,同时 ...