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: 22exist: 0
*************************** 2. row ***************************id: 4
weight: 44exist: 1
*************************** 3. row ***************************id: 5
weight: 55exist: 0
*************************** 4. row ***************************id: 6
weight: 66exist: 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

 

转载于:https://www.cnblogs.com/onlysun/p/4524404.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/405794.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

oracle cdc 关闭,Oracle CDC部署流程

一、ORACLE环境检查查oracle数据库版本(>9.2.0.4.0).select * from v$version;BANNEROracle Database 10g Enterprise Edition Release 10.2.0.1.0 - ProdPL/SQL Release 10.2.0.1.0 - ProductionCORE 10.2.0.1.0 ProductionTNS for 32-bit Windows: Version …

几个重要的RedHat Linux内核文件介绍 (1)

From:http://tech.sina.com.cn/s/s/2006-06-27/061923370.shtml Linux服务器内核编译基础 mynix编译自www.linux.org之Linux HowTo之Kernel HowTo 在网络中&#xff0c;不少服务器采用的是Linux系统。为了进一步提高服务器的性能&#xff0c;可能需要根据特定的硬件及需求重新…

Qt 两个Ui 界面传值

一、说明 A子界面 B主界面 &#xff0c; 实现A往B传值&#xff0c;B显示. 二、利用emit和slot实现 2.1 对A.h 添加声明 signals: void sendData(QString); //用来传递数据的信号 2.2在A.cpp中适当位置将数据进行发射 emit sendData(ui->lineEdit->text());…

有哪些是你成为一名开发之后才知道的事情

目录 前言 疑问1成为一名开发真的很难嘛&#xff1f; 疑问2作为一名开发的工资一定很高吗 疑问3开发一定加班会很厉害嘛 疑问4一定要去大厂嘛 疑问5程序员是个很好的职业选择吗 疑问6毕业前参加培训好吗 疑问7入行之后要不断提升自己的能力吗 疑问8大学四年该如何度过 疑问…

她们分别买了什么?

using System; using System.Collections.Generic; using System.Text; class Program { static void Main(string[] args) { /* * 测试 9&#xff0e;她们分别买了什么? */ WhatWasBought(); …

[发布] 矩阵乘法及其对于编程求斐波那契数列的某一项的应用

需要PDF的读者可以向我索要。 如果发现有翻印与用于商业用途&#xff0c;将予追究。 编者注&#xff1a;本文中如果没有特殊说明&#xff0c;除法均只取整数部分&#xff0c;忽略小数部分。 感谢大家对我的支持&#xff01;同时感谢ysy大聚聚。转载于:https://www.cnblogs.com…

oracle新建用户sql局域,oracle 新建数据库,及创建用户,表空间,sqlplus导入导出数据库...

oracle11G新建数据库&#xff1a;默认下一步&#xff1a;默认下一步&#xff1a;默认下一步&#xff1a;填写数据库名下一步&#xff1a;默认下一步&#xff1a;完成&#xff0c;再按指示确定&#xff0c;就完成了数据库的创建。数据库创建完后&#xff0c;在oracle11G Net Man…

QIcon 给按钮和动作添加图片

对Qt中资源文件的引用时&#xff0c;QAction/QPushbutton添加图标时&#xff0c;需要用到图片的路径。 1、先添加资源文件&#xff0c;项目->添加新的文件->Qt resource files->添加前缀->添加文件。 2、复制需要文件的路径&#xff1b;&#xff08;工程树对应图…

linux下xargs命令用法详解

From:http://biancheng.dnbcw.info/shell/268829.html xargs在 linux中是个很有用的命令,它经常和其他命令组合起来使用,非常的灵活.xargs是给命令传递参数的一个过滤器,也是组合多个命令的一个工具.它把一个数据流分割为一些足够小的块,以方便过滤器和命令进行处理.由此这个命…

监理公司的核心竞争力

企业竞争力模型&#xff0c;无疑要看迈克尔波特的文章&#xff0c;从企业竞争、行业竞争至国家竞争&#xff0c;都有成熟的竞争理论。同多数IT公司一样,监理公司核心竞争力仍然是创新与复制能力.只不过IT产品是监理咨询与服务&#xff0c;纯粹服务产品的研发和管理&#xff0c;…

Altera 速度等级

~~ 转载于:https://www.cnblogs.com/agllero/p/4533848.html

STM32项目中一种在线升级/应用升级OTA-IAP设计方案

STM32 OTA-IAP设计方案 OTA是Over-the-Air的简写&#xff0c;即空中下载技术&#xff0c;通过网络远程给用户进行系统更新和升级。IAP是In Application Programming的简写&#xff0c;IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写&#xff0c;目的是为了在…

oracle 主键列创建自增长,powerdesigner创建oracle 数据库表,设置表主键列为自动增长。 ....

1 在表视图的列上创建。 双击表视图&#xff0c;打开table properties ———>columens &#xff0c; 双击要设置的列(显示列的序号的那个按钮&#xff0c;单击后&#xff0c;会显示横向的黑色箭头)。 打开column properties 对话框。在 ‘general’ 项中&#xff0c; 最下面…

嵌入式GUI FTK支持输入法

From: http://blog.csdn.net/absurd/article/details/5318285 春节期间给FTK增加输入法支持&#xff0c;目前支持拼音输入法&#xff0c;五笔输入法和手写输入法。手写输入法只是实现了框架&#xff0c;识别引擎才开个头&#xff0c;这是今年FTK开发的重点任务。拼音输入法&…

STM32程序占用的内存容量计算

STM32中程序占用内存容量 Keil MDK下Code, RO-data,RW-data,ZI-data这几个段: Code存储程序代码。RO-data存储const常量和指令。RW-data存储初始化值不为0的全局变量。ZI-data存储未初始化的全局变量或初始化值为0的全局变量。占用的FlashCode RO Data RW Data; 运行消耗的…

域名解析

搭建网站&#xff1a;要将域名指向主机服务商提供的IP地址&#xff0c;请选择「A记录」&#xff1b;要将域名指向主机服务商提供的另一个域名&#xff0c;请选择「CNAME记录」。建立邮箱&#xff1a;需要设置「MX记录」&#xff0c;根据邮箱服务商提供的MX记录填写。A记录&…

【原创】最值得推荐wince应用和wince驱动入门书籍

作者&#xff1a;wogoyixikexiegliet应用方向&#xff1f; C&#xff0c;c#----------本人不做应用只知道用这两个语言用到&#xff0c;不敢推荐 -------也来补充一下。《PROGRAMMING MICROSOFT WINDOWS CE.NET》第三版英文原著Inside Windows CE - John Murray Programm…

oracle中错位函数,Oracle中的一些函数

select initcap(ename) from emp; 该语句能够使 ename 列的首字母大写。select concat(hello ,world) from dual; 该语句是hello 和 world 被连接起来 concat()select ename, substr(ename,-2,2) from emp; 该语句呢,这个substr(ename , -2 ,2 ) 我一直有个疑问 , 那就是 …