MySQL浅谈 LEFT JOIN
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的更多相关文章
- Python 基于python+mysql浅谈redis缓存设计与数据库关联数据处理
基于python+mysql浅谈redis缓存设计与数据库关联数据处理 by:授客 QQ:1033553122 测试环境 redis-3.0.7 CentOS 6.5-x86_64 python 3 ...
- 浅谈 Fork/Join
fork/join的java7新添加的功能,能够把它理解成一个并发框架. 我们通过fork/join能将一个可分解的大任务.分解成多个子任务同步运行.运行完成后,在将各子任务的结果进行合并,得到终于的 ...
- mysql浅谈--事务ACID特性
mysql MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管 ...
- MYSQL优化浅谈,工具及优化点介绍,mysqldumpslow,pt-query-digest,explain等
MYSQL优化浅谈 msyql是开发常用的关系型数据库,快速.稳定.开源等优点就不说了. 个人认为,项目上线,标志着一个项目真正的开始.从运维,到反馈,到再分析,再版本迭代,再优化… 这是一个漫长且考 ...
- 浅谈mysql配置优化和sql语句优化【转】
做优化,我在这里引用淘宝系统分析师蒋江伟的一句话:只有勇于承担,才能让人有勇气,有承担自己的错误的勇气.有承担错误的勇气,就有去做事得勇气.无论做什么事,只要是对的,就要去做,勇敢去做.出了错误,承担 ...
- sql语句浅谈以及mysql遇到的问题解决见解
mysql数据库基本操作: .显示数据库和查看mysql版本 show databases; select version(); select user();查看用户 .选择数据库 use 数据库名; ...
- MySql主从配置实践及其优势浅谈
MySql主从配置实践及其优势浅谈 1.增加两个MySQL,我将C:\xampp\mysql下的MYSQL复制了一份,放到D:\Mysql2\Mysql5.1 修改my.ini(linux下应该是my ...
- 浅谈mysql主从复制的高可用解决方案
1.熟悉几个组件(部分摘自网络)1.1.drbd —— DRBD(Distributed Replicated Block Device),DRBD号称是 "网络 RAID" ...
- Linux CentOS下MySQL的安装配置之浅谈
前期必备安装:VMware虚拟机,CentOS镜像[注意:Linux下使用CentOS MySQL是不用在官网下载的,只需要配置就OK了] 下面开始正式操作: //CentOS安装MySQL之浅谈 ...
随机推荐
- 基础环境之Docker入门
随着Docker技术的不断成熟,越来越多的企业开始考虑使用Docker.Docker有很多的优势,本文主要讲述了Docker的五个最重要优势,即持续集成.版本控制.可移植性.隔离性和安全性. 有了Do ...
- 用Python让单片机“行动”起来——MicroPython实战入门篇
MicroPython以微控制器作为目标,从而使得Python可以用来控制硬件.说到MicroPython,也许有人会感到陌生.而说到和它密切相关的Python,是否会恍然大悟呢?Python属于解释 ...
- ArcGis连接oracle失败:ORA-6413:连接未打开
问题: 通过ARCMap 添加Oracle数据库连接时提示,ORA-6413:连接未打开. 运行环境: ArcGis 10.2 Oracle 10g 解决方法: 通过上网查找解决方法,网友说" ...
- lbp特征提取(等价模式)
LBP等价模式 考察LBP算子的定义可知,一个LBP算子可以产生多种二进制模式(p个采样点)如:3x3邻域有p=8个采样点,则可得到2^8=256种二进制模式:5x5邻域有p=24个采样点,则可得到2 ...
- 北斗时钟同步系统-GPS卫星授时设备-NTP网络校时服务器
北斗时钟同步系统-GPS卫星授时设备-NTP网络校时服务器 北斗时钟同步系统-GPS卫星授时设备-NTP网络校时服务器 北斗时钟同步系统-GPS卫星授时设备-NTP网络校时服务器 论述当下网络时间同步 ...
- chrome调试工具高级不完整使用指南(实战一)
三.chrome调试工具实战 3.1 获取界面对应的HTML和修改样式 我们以博客园为例子来分析. 通过上面的操作就可以定位到对应的HTML代码 左侧菜单显示的就是当前指定元素层叠样式的一个情况 上面 ...
- 通过Chocolatey软件包管理器安装.NET Core
在Linux的世界里,有了yum/apt-get百分之九十的软件都可以通过它来安装管理.但是在Windows系统上,装个软件还是挺折腾的.比如我要装个Chrome浏览器,我先得打开IE浏览器吧,我还打 ...
- Java8函数式接口以及lambda表达式实践
罗列一下遇到可以转换成lamada表达式的场景,仅供参考,如有更好的方式,欢迎在评论区留言. 1.计算订单总金额 订单总金额一般是在后台循环叠加每个购买商品的金额已获取到,通常的方式如下 BigDec ...
- 利用TortoiseGit对Coding项目进行版本管理
Git配置: 1),首先去Git官网下载最新的Git,https://git-for-windows.github.io/ 2),下载对应的版本,然后一路next点击安装. Git与Coding联通 ...
- 解决Fiddler出现无线弹框 "creation of the root certificate was not successful”的问题
打开Fiddler 访问:http://localhost:8888/ 安装证书,如果提示没有证书(8888是你在Tool->Fiddler Option->Connections设置的F ...