On条件(在“A left join b on conditional_expr”)决定如何从table B 中检索数据行(Matching-State);

如果B中没有行匹配On 条件,额外的B的所有数据列被设为null;
    如果Matching-Stage阶段,where语句的任何限制条件都不会使用,只有Match-Stage阶段之后,where语句的条件才回被使用,它会过滤从matching-stage阶段检索出的数据行。

mysql> show create table product\G;
*************************** 1. row ***************************
Table: product
Create Table: CREATE TABLE `product` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`amount` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> show create table product_details\G;
*************************** 1. row ***************************
Table: product_details
Create Table: CREATE TABLE `product_details` (
`id` int(10) unsigned NOT NULL,
`weight` int(10) unsigned DEFAULT NULL,
`exist` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> select * from product\G;
*************************** 1. row ***************************
id: 1
amount: 100
*************************** 2. row ***************************
id: 2
amount: 200
*************************** 3. row ***************************
id: 3
amount: 300
*************************** 4. row ***************************
id: 4
amount: 400
4 rows in set (0.00 sec)
mysql> select * from product_details\G;
*************************** 1. row ***************************
id: 2
weight: 22
exist: 0
*************************** 2. row ***************************
id: 4
weight: 44
exist: 1
*************************** 3. row ***************************
id: 5
weight: 55
exist: 0
*************************** 4. row ***************************
id: 6
weight: 66
exist: 1
4 rows in set (0.00 sec)
mysql> select * from product left join product_details
-> on product.id = product_details.id;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 2 | 200 | 2 | 22 | 0 |
| 4 | 400 | 4 | 44 | 1 |
| 1 | 100 | NULL | NULL | NULL |
| 3 | 300 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
4 rows in set (0.00 sec)

on条件语句和where条件语句有区别吗?

A question: 下面两条查询语句结果集有区别吗?

mysql> select * from product left join product_details
-> on product.id = product_details.id
-> and product_details.id = 2;
mysql> select * from product left join product_details
-> on product.id = product_details.id
-> where product_details.id = 2;

<===================================================================>

答案:

mysql> select * from product left join product_details
-> on product.id = product_details.id
-> and product_details.id = 2;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 1 | 100 | NULL | NULL | NULL |
| 2 | 200 | 2 | 22 | 0 |
| 3 | 300 | NULL | NULL | NULL |
| 4 | 400 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
4 rows in set (0.01 sec)
mysql> select * from product left join product_details   
-> on product.id = product_details.id
-> where product_details.id = 2;
+----+--------+----+--------+-------+
| id | amount | id | weight | exist |
+----+--------+----+--------+-------+
| 2 | 200 | 2 | 22 | 0 |
+----+--------+----+--------+-------+
1 row in set (0.00 sec)

第一条查询检索出product表的所有行,并用on condition来决定 做左连接的product_details表那些行被检索。

第二条查询做一样的left-JOIN,它用where语句条件过滤掉不匹配的行。

mysql> select * from product left join product_details
-> on product.id = product_details.id
-> and product.amount = 100;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 1 | 100 | NULL | NULL | NULL |
| 2 | 200 | NULL | NULL | NULL |
| 3 | 300 | NULL | NULL | NULL |
| 4 | 400 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
4 rows in set (0.03 sec)

product表的所有行都被检索,然而,在product_details表中没找到匹配(没有行匹配该条件product_id = product_details.id and product.amounbt =100);

mysql> select * from product left join product_details
-> on product.id = product_details.id
-> and product.amount = 200;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 2 | 200 | 2 | 22 | 0 |
| 1 | 100 | NULL | NULL | NULL |
| 3 | 300 | NULL | NULL | NULL |
| 4 | 400 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
4 rows in set (0.00 sec)

只有一行在product_details中匹配

left join with where ... is null clause:

where-condition阶段在matching-stage阶段之后发生,这意味这where is null 语句会从matching-stage阶段产生的结果过滤那些行不满足 matching-condition(on ...and)

如果你使用超过一个条件在on 语句中(and....and...),这时会变的困惑。
    一个简单的方法理解复杂的matching-condition 搭配where ... is null 语句:

1: 把 is null 语句看作matching-condition的否定;

2:用逻辑规则: !(A and B) == !A or !B

下面列子:

mysql> select a.* from product a left join product_details b
-> on a.id = b.id and b.weight != 44 and b.exist = 0
-> where b.id is null;
+----+--------+
| id | amount |
+----+--------+
| 1 | 100 |
| 3 | 300 |
| 4 | 400 |
+----+--------+
3 rows in set (0.00 sec)

检验下matching clause(on clause):

on a.id = b.id and b.weight != 44 and b.exist = 0

记住我们认为is null 语句作为 matching-condition的否定.

这意味着我们检索下面这些行:

! ( exist(b.id that equals to a.id)  AND  b.weight !=44  AND  b.exist=0 ) ! exist(b.id that equals to a.id) || ! (b.weight !=44) || ! (b.exist=0)
! exist(b.id that equals to a.id) || b.weight =44 || b.exist=1

像在C语言中,&&,||逻辑与,或操作符从左到右计算一样,如果一个操作符的结果足以决定最终结果,第二个操作开始不会计算(短路操作)。

在我们这种情况下,意味着,我们检索与A中所有行不匹配的b表中的id ,如果匹配,再检索b.weight = 44 或者b.exist =1.

mysql> select a.* from product a left join product_details b
-> on a.id = b.id and b.weight != 44 and b.exist = 1
-> where b.id is null;
+----+--------+
| id | amount |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
| 4 | 400 |
+----+--------+
4 rows in set (0.00 sec)
! ( exist(bid that equals to aid) AND b.weight !=44 AND b.exist=1 )
!exist(bid that equals to aid) || !(b.weight !=44) || !(b.exist=1)
!exist(bid that equals to aid) || b.weight =44 || b.exist=0

THE BATTLE BETWEEN THE MATCHING-CONDITIONS AND THE WHERE-CONDITIONS

            你可以获得一样的结果(A.*)如果你把基本的匹配条件放在on语句中,而剩余的条件的否定放在where子句中,例如:

 

mysql> select a.* from product a left join product_details b
-> on a.id = b.id and b.weight != 44 and b.exist = 0
-> where b.id is null;
+----+--------+
| id | amount |
+----+--------+
| 1 | 100 |
| 3 | 300 |
| 4 | 400 |
+----+--------+
3 rows in set (0.00 sec)

同样的结果,不同的写法:

mysql> select a.* from product a left join product_details b
-> on a.id = b.id
-> where b.id is null or b.weight = 44 or b.exist = 1;
+----+--------+
| id | amount |
+----+--------+
| 4 | 400 |
| 1 | 100 |
| 3 | 300 |
+----+--------+
3 rows in set (0.00 sec)
mysql> select a.* from product a left join product_details b
-> on a.id = b.id and b.weight != 44 and b.exist != 0
-> where b.id is null;
+----+--------+
| id | amount |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
| 4 | 400 |
+----+--------+
4 rows in set (0.00 sec) mysql> select a.* from product a left join product_details b
-> on a.id = b.id
-> where b.id is null or b.weight = 44 or b.exist = 0;
+----+--------+
| id | amount |
+----+--------+
| 2 | 200 |
| 4 | 400 |
| 1 | 100 |
| 3 | 300 |
+----+--------+
4 rows in set (0.00 sec)

这两种查询真的一样吗?

这两种检索一样的结果集如果你只需要第一个表中的结果(e.g. A.*),但是当你在连接表中检索数据时,返回的结果集就跟之前不一样的了,where语句会过滤matching-state返回的数据行;

mysql> select * from product a left join product_details b   
on a.id = b.id
where b.id is null or b.weight = 44 or b.exist = 1;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 4 | 400 | 4 | 44 | 1 |
| 1 | 100 | NULL | NULL | NULL |
| 3 | 300 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
3 rows in set (0.00 sec) mysql> select * from product a left join product_details b
on a.id = b.id and b.weight != 44 and b.exist != 0
where b.id is null;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 1 | 100 | NULL | NULL | NULL |
| 2 | 200 | NULL | NULL | NULL |
| 3 | 300 | NULL | NULL | NULL |
| 4 | 400 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
4 rows in set (0.00 sec)

如果你用left join来找出那些不存在别的表中的数据行时,在where 语句中的col_name is null部分,col_name对应的列必须被修饰为not null;

MySQL浅谈 LEFT JOIN的更多相关文章

  1. Python 基于python+mysql浅谈redis缓存设计与数据库关联数据处理

    基于python+mysql浅谈redis缓存设计与数据库关联数据处理 by:授客  QQ:1033553122 测试环境 redis-3.0.7 CentOS 6.5-x86_64 python 3 ...

  2. 浅谈 Fork/Join

    fork/join的java7新添加的功能,能够把它理解成一个并发框架. 我们通过fork/join能将一个可分解的大任务.分解成多个子任务同步运行.运行完成后,在将各子任务的结果进行合并,得到终于的 ...

  3. mysql浅谈--事务ACID特性

    mysql MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管 ...

  4. MYSQL优化浅谈,工具及优化点介绍,mysqldumpslow,pt-query-digest,explain等

    MYSQL优化浅谈 msyql是开发常用的关系型数据库,快速.稳定.开源等优点就不说了. 个人认为,项目上线,标志着一个项目真正的开始.从运维,到反馈,到再分析,再版本迭代,再优化… 这是一个漫长且考 ...

  5. 浅谈mysql配置优化和sql语句优化【转】

    做优化,我在这里引用淘宝系统分析师蒋江伟的一句话:只有勇于承担,才能让人有勇气,有承担自己的错误的勇气.有承担错误的勇气,就有去做事得勇气.无论做什么事,只要是对的,就要去做,勇敢去做.出了错误,承担 ...

  6. sql语句浅谈以及mysql遇到的问题解决见解

    mysql数据库基本操作: .显示数据库和查看mysql版本 show databases; select version(); select user();查看用户 .选择数据库 use 数据库名; ...

  7. MySql主从配置实践及其优势浅谈

    MySql主从配置实践及其优势浅谈 1.增加两个MySQL,我将C:\xampp\mysql下的MYSQL复制了一份,放到D:\Mysql2\Mysql5.1 修改my.ini(linux下应该是my ...

  8. 浅谈mysql主从复制的高可用解决方案

    1.熟悉几个组件(部分摘自网络)1.1.drbd     —— DRBD(Distributed Replicated Block Device),DRBD号称是 "网络 RAID" ...

  9. Linux CentOS下MySQL的安装配置之浅谈

    前期必备安装:VMware虚拟机,CentOS镜像[注意:Linux下使用CentOS   MySQL是不用在官网下载的,只需要配置就OK了] 下面开始正式操作: //CentOS安装MySQL之浅谈 ...

随机推荐

  1. 漂亮的提示框SweetAlert使用教程

    一.简介 所使用过的弹出框插件,SweetAlert是最好用的.发展至今,已经有两个版本,一个是原版 t4t5/sweetalert , 一个是分支版 limonte/sweetalert2 ,更新相 ...

  2. 第七章:Python基础のXML操作和面向对象(一)

    本課主題 XML介绍与操作实战 shutil 模块介绍与操作实战 subprocess 模块介绍与操作实战 初探面向对象与操作实战 本周作业 XML介绍和操作实战 對於浏览器返回的字符串有以下幾種: ...

  3. Python模块学习------ 多线程threading(2)

    一.避免使用thread模块,使用threading模块的原因: 1. 更高级别的threading模块更为先进,对线程的支持更加完善.而且使用thread模块的属性有可能会与threading 出现 ...

  4. 【zkw费用流】[网络流24题]餐巾计划问题

    题目描述 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,-,N).餐厅可以从三种途径获得餐巾. (1)购买新的餐巾,每块需p分: (2)把用过的餐巾送到快洗部,洗一块需m天,费用需f分(f ...

  5. 记一个http-proxy-middleware 代理访问nginx映射的接口不通过的问题(connection close)

    工作过程中遇见一个问题,使用Vue-cli 搭建了一个工程,由于跨域的问题 使用了自带的dev-server Express Server(A后台) http-proxy-middleware 去访问 ...

  6. Django 1.10中文文档-第一个应用Part1-请求与响应

    在本教程中,我们将引导您完成一个投票应用程序的创建,它包含下面两部分: 一个可以进行投票和查看结果的公开站点: 一个可以进行增删改查的后台admin管理界面: 我们假设你已经安装了Django.您可以 ...

  7. Python3基础1

    Python介绍及特点 发展史 Python 2 or 3? 安装Python3 Hello World程序 变量 用户输入 模块初识 .pyc是个什么? 数据类型初识 数据运算 表达式if ...e ...

  8. JavaScript判断对象是否含有某个属性

    两种方式,但稍有区别 1,in 运算符 1 2 3 var obj = {name:'jack'}; alert('name' in obj); // --> true alert('toStr ...

  9. 渗透测试入门DVWA 教程1:环境搭建

    首先欢迎新萌入坑.哈哈.你可能抱着好奇心或者疑问.DVWA 是个啥? DVWA是一款渗透测试的演练系统,在圈子里是很出名的.如果你需要入门,并且找不到合适的靶机,那我就推荐你用DVWA. 我们通常将演 ...

  10. CTF---安全杂项入门第二题 A记录

    A记录分值:20 来源: sammie 难度:中 参与人数:2255人 Get Flag:566人 答题人数:621人 解题通过率:91% 他在看什么视频,好像很好看,不知道是什么网站的. 还好我截取 ...