热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

msyqlleftjoinon后面多个条件_MySQL

msyqlleftjoinon后面多个条件
bitsCN.com

即使你认为自己已对 MySQL 的 LEFT JOIN 理解深刻,但我敢打赌,这篇文章肯定能让你学会点东西!

ON 子句与 WHERE 子句的不同一种更好地理解带有 WHERE ... IS NULL 子句的复杂匹配条件的简单方法
Matching-Conditions 与 Where-conditions 的不同

关于 “A LEFT JOIN B ON 条件表达式” 的一点提醒

ON 条件(“A LEFT JOIN B ON 条件表达式”中的ON)用来决定如何从 B 表中检索数据行。

如果 B 表中没有任何一行数据匹配 ON 的条件,将会额外生成一行所有列为 NULL 的数据

在匹配阶段 WHERE 子句的条件都不会被使用。仅在匹配阶段完成以后,WHERE 子句条件才会被使用。它将从匹配阶段产生的数据中检索过滤。

让我们看一个 LFET JOIN 示例:

01 mysql> CREATE TABLE `product` ( 02 `id` int(10) unsigned NOT NULL auto_increment, 03 `amount` int(10) unsigned default NULL, 04 PRIMARY KEY (`id`) 05 ) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 06 07 mysql> CREATE TABLE `product_details` ( 08 `id` int(10) unsigned NOT NULL, 09 `weight` int(10) unsigned default NULL, 10 `exist` int(10) unsigned default NULL, 11 PRIMARY KEY (`id`) 12 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 13 14 mysql> INSERT INTO product (id,amount) 15 VALUES (1,100),(2,200),(3,300),(4,400); 16 Query OK, 4 rows affected (0.00 sec) 17 Records: 4 Duplicates: 0 Warnings: 0 18 19 mysql> INSERT INTO product_details (id,weight,exist) 20 VALUES (2,22,0),(4,44,1),(5,55,0),(6,66,1); 21 Query OK, 4 rows affected (0.00 sec) 22 Records: 4 Duplicates: 0 Warnings: 0 23 24 mysql> SELECT * FROM product; 25 +----+--------+ 26 | id | amount | 27 +----+--------+ 28 | 1 | 100 | 29 | 2 | 200 | 30 | 3 | 300 | 31 | 4 | 400 | 32 +----+--------+ 33 4 rows in set (0.00 sec) 34 35 mysql> SELECT * FROM product_details; 36 +----+--------+-------+ 37 | id | weight | exist | 38 +----+--------+-------+ 39 | 2 | 22 | 0 | 40 | 4 | 44 | 1 | 41 | 5 | 55 | 0 | 42 | 6 | 66 | 1 | 43 +----+--------+-------+ 44 4 rows in set (0.00 sec) 45 46 mysql> SELECT * FROM product LEFT JOIN product_details 47 ON (product.id = product_details.id); 48 +----+--------+------+--------+-------+ 49 | id | amount | id | weight | exist | 50 +----+--------+------+--------+-------+ 51 | 1 | 100 | NULL | NULL | NULL | 52 | 2 | 200 | 2 | 22 | 0 | 53 | 3 | 300 | NULL | NULL | NULL | 54 | 4 | 400 | 4 | 44 | 1 | 55 +----+--------+------+--------+-------+ 56 4 rows in set (0.00 sec)

ON 子句和 WHERE 子句有什么不同?

一个问题:下面两个查询的结果集有什么不同么?

1 1. SELECT * FROM product LEFT JOIN product_details 2 ON (product.id = product_details.id) 3 AND product_details.id=2; 4 2. SELECT * FROM product LEFT JOIN product_details 5 ON (product.id = product_details.id) 6 WHERE product_details.id=2;

用例子来理解最好不过了:

01 mysql> SELECT * FROM product LEFT JOIN product_details 02 ON (product.id = product_details.id) 03 AND product_details.id=2; 04 +----+--------+------+--------+-------+ 05 | id | amount | id | weight | exist | 06 +----+--------+------+--------+-------+ 07 | 1 | 100 | NULL | NULL | NULL | 08 | 2 | 200 | 2 | 22 | 0 | 09 | 3 | 300 | NULL | NULL | NULL | 10 | 4 | 400 | NULL | NULL | NULL | 11 +----+--------+------+--------+-------+ 12 4 rows in set (0.00 sec) 13 14 mysql> SELECT * FROM product LEFT JOIN product_details 15 ON (product.id = product_details.id) 16 WHERE product_details.id=2; 17 +----+--------+----+--------+-------+ 18 | id | amount | id | weight | exist | 19 +----+--------+----+--------+-------+ 20 | 2 | 200 | 2 | 22 | 0 | 21 +----+--------+----+--------+-------+ 22 1 row in set (0.01 sec)

第一条查询使用 ON 条件决定了从 LEFT JOIN的 product_details表中检索符合的所有数据行。

第二条查询做了简单的LEFT JOIN,然后使用 WHERE 子句从 LEFT JOIN的数据中过滤掉不符合条件的数据行。

再来看一些示例:

01 mysql> 02 mysql> SELECT * FROM product LEFT JOIN product_details 03 ON product.id = product_details.id 04 AND product.amount=100; 05 +----+--------+------+--------+-------+ 06 | id | amount | id | weight | exist | 07 +----+--------+------+--------+-------+ 08 | 1 | 100 | NULL | NULL | NULL | 09 | 2 | 200 | NULL | NULL | NULL | 10 | 3 | 300 | NULL | NULL | NULL | 11 | 4 | 400 | NULL | NULL | NULL | 12 +----+--------+------+--------+-------+ 13 4 rows in set (0.00 sec)

所有来自product表的数据行都被检索到了,但没有在product_details表中匹配到记录(product.id = product_details.id AND product.amount=100 条件并没有匹配到任何数据)

01 mysql> SELECT * FROM product LEFT JOIN product_details 02 ON (product.id = product_details.id) 03 AND product.amount=200; 04 +----+--------+------+--------+-------+ 05 | id | amount | id | weight | exist | 06 +----+--------+------+--------+-------+ 07 | 1 | 100 | NULL | NULL | NULL | 08 | 2 | 200 | 2 | 22 | 0 | 09 | 3 | 300 | NULL | NULL | NULL | 10 | 4 | 400 | NULL | NULL | NULL | 11 +----+--------+------+--------+-------+ 12 4 rows in set (0.01 sec)

同样,所有来自product表的数据行都被检索到了,有一条数据匹配到了。

使用 WHERE ... IS NULL 子句的 LEFT JOIN

当你使用 WHERE ... IS NULL 子句时会发生什么呢?

如前所述,WHERE 条件查询发生在 匹配阶段之后,这意味着 WHERE ... IS NULL 子句将从匹配阶段后的数据中过滤掉不满足匹配条件的数据行。

纸面上看起来很清楚,但是当你在 ON 子句中使用多个条件时就会感到困惑了。

我总结了一种简单的方式来理解上述情况:

将 IS NULL 作为否定匹配条件使用 !(A and B) == !A OR !B 逻辑判断

看看下面的示例:

01 mysql> SELECT a.* FROM product a LEFT JOIN product_details b 02 ON a.id=b.id AND b.weight!=44 AND b.exist=0 03 WHERE b.id IS NULL; 04 +----+--------+ 05 | id | amount | 06 +----+--------+ 07 | 1 | 100 | 08 | 3 | 300 | 09 | 4 | 400 | 10 +----+--------+ 11 3 rows in set (0.00 sec)

让我们检查一下 ON 匹配子句:

1 (a.id=b.id) AND (b.weight!=44) AND (b.exist=0)

我们可以把 IS NULL 子句 看作是否定匹配条件。

这意味着我们将检索到以下行:

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

就像在C语言中的逻辑 AND 和 逻辑 OR表达式一样,其操作数是从左到右求值的。如果第一个参数做够判断操作结果,那么第二个参数便不会被计算求值(短路效果)

看看别的示例:

01 mysql> SELECT a.* FROM product a LEFT JOIN product_details b 02 ON a.id=b.id AND b.weight!=44 AND b.exist=1 03 WHERE b.id IS NULL; 04 +----+--------+ 05 | id | amount | 06 +----+--------+ 07 | 1 | 100 | 08 | 2 | 200 | 09 | 3 | 300 | 10 | 4 | 400 | 11 +----+--------+ 12 4 rows in set (0.00 sec)

Matching-ConditionsWhere-conditions 之战

如果你吧基本的查询条件放在 ON 子句中,把剩下的否定条件放在 WHERE 子句中,那么你会获得相同的结果。

例如,你可以不这样写:

1 SELECT a.* FROM product a LEFT JOIN product_details b 2 ON a.id=b.id AND b.weight!=44 AND b.exist=0 3 WHERE b.id IS NULL;

你可以这样写:

1 SELECT a.* FROM product a LEFT JOIN product_details b 2 ON a.id=b.id 3 WHERE b.id is null OR b.weight=44 OR b.exist=1 01 mysql> SELECT a.* FROM product a LEFT JOIN product_details b 02 ON a.id=b.id 03 WHERE b.id is null OR b.weight=44 OR b.exist=1; 04 +----+--------+ 05 | id | amount | 06 +----+--------+ 07 | 1 | 100 | 08 | 3 | 300 | 09 | 4 | 400 | 10 +----+--------+ 11 3 rows in set (0.00 sec)

你可以不这样写:

1 SELECT a.* FROM product a LEFT JOIN product_details b 2 ON a.id=b.id AND b.weight!=44 AND b.exist!=0 3 WHERE b.id IS NULL;

可以这样写:

1 SELECT a.* FROM product a LEFT JOIN product_details b 2 ON a.id=b.id 3 WHERE b.id is null OR b.weight=44 OR b.exist=0; 01 mysql> SELECT a.* FROM product a LEFT JOIN product_details b 02 ON a.id=b.id 03 WHERE b.id is null OR b.weight=44 OR b.exist=0; 04 +----+--------+ 05 | id | amount | 06 +----+--------+ 07 | 1 | 100 | 08 | 2 | 200 | 09 | 3 | 300 | 10 | 4 | 400 | 11 +----+--------+ 12 4 rows in set (0.00 sec)

这些查询真的效果一样?

如果你只需要第一个表中的数据的话,这些查询会返回相同的结果集。有一种情况就是,如果你从 LEFT JOIN的表中检索数据时,查询的结果就不同了。

如前所属,WHERE 子句是在匹配阶段之后用来过滤的。

例如:

01 mysql> SELECT * FROM product a LEFT JOIN product_details b 02 ON a.id=b.id AND b.weight!=44 AND b.exist=1 03 WHERE b.id is null; 04 +----+--------+------+--------+-------+ 05 | id | amount | id | weight | exist | 06 +----+--------+------+--------+-------+ 07 | 1 | 100 | NULL | NULL | NULL | 08 | 2 | 200 | NULL | NULL | NULL | 09 | 3 | 300 | NULL | NULL | NULL | 10 | 4 | 400 | NULL | NULL | NULL | 11 +----+--------+------+--------+-------+ 12 4 rows in set (0.00 sec) 13 14 mysql> SELECT * FROM product a LEFT JOIN product_details b 15 ON a.id=b.id 16 WHERE b.id IS NULL OR b.weight=44 OR b.exist=0; 17 +----+--------+------+--------+-------+ 18 | id | amount | id | weight | exist | 19 +----+--------+------+--------+-------+ 20 | 1 | 100 | NULL | NULL | NULL | 21 | 2 | 200 | 2 | 22 | 0 | 22 | 3 | 300 | NULL | NULL | NULL | 23 | 4 | 400 | 4 | 44 | 1 | 24 +----+--------+------+--------+-------+ 25 4 rows in set (0.00 sec)

总附注:

如果你使用 LEFT JOIN 来寻找在一些表中不存在的记录,你需要做下面的测试:WHERE 部分的 col_name IS NULL(其中 col_name 列被定义为 NOT NULL),MYSQL 在查询到一条匹配 LEFT JOIN 条件后将停止搜索更多行(在一个特定的组合键下)。

bitsCN.com
推荐阅读
  • 31.项目部署
    目录1一些概念1.1项目部署1.2WSGI1.3uWSGI1.4Nginx2安装环境与迁移项目2.1项目内容2.2项目配置2.2.1DEBUG2.2.2STAT ... [详细]
  • 在数据分析工作中,我们通常会遇到这样的问题,一个业务部门由若干业务组构成,需要筛选出每个业务组里业绩前N名的业务员。这其实是一个分组排序的 ... [详细]
  • 本文介绍了Linux Shell中括号和整数扩展的使用方法,包括命令组、命令替换、初始化数组以及算术表达式和逻辑判断的相关内容。括号中的命令将会在新开的子shell中顺序执行,括号中的变量不能被脚本余下的部分使用。命令替换可以用于将命令的标准输出作为另一个命令的输入。括号中的运算符和表达式符合C语言运算规则,可以用在整数扩展中进行算术计算和逻辑判断。 ... [详细]
  • 这篇文章主要介绍了Python拼接字符串的七种方式,包括使用%、format()、join()、f-string等方法。每种方法都有其特点和限制,通过本文的介绍可以帮助读者更好地理解和运用字符串拼接的技巧。 ... [详细]
  • 本文介绍了在Windows系统上使用C语言命令行参数启动程序并传递参数的方法,包括接收参数程序的代码和bat文件的编写方法,同时给出了程序运行的结果。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • C语言判断正整数能否被整除的程序
    本文介绍了使用C语言编写的判断正整数能否被整除的程序,包括输入一个三位正整数,判断是否能被3整除且至少包含数字3的方法。同时还介绍了使用qsort函数进行快速排序的算法。 ... [详细]
  • 本文介绍了使用Python解析C语言结构体的方法,包括定义基本类型和结构体类型的字典,并提供了一个示例代码,展示了如何解析C语言结构体。 ... [详细]
  • C语言常量与变量的深入理解及其影响
    本文深入讲解了C语言中常量与变量的概念及其深入实质,强调了对常量和变量的理解对于学习指针等后续内容的重要性。详细介绍了常量的分类和特点,以及变量的定义和分类。同时指出了常量和变量在程序中的作用及其对内存空间的影响,类似于const关键字的只读属性。此外,还提及了常量和变量在实际应用中可能出现的问题,如段错误和野指针。 ... [详细]
  • 恶意软件分析的最佳编程语言及其应用
    本文介绍了学习恶意软件分析和逆向工程领域时最适合的编程语言,并重点讨论了Python的优点。Python是一种解释型、多用途的语言,具有可读性高、可快速开发、易于学习的特点。作者分享了在本地恶意软件分析中使用Python的经验,包括快速复制恶意软件组件以更好地理解其工作。此外,作者还提到了Python的跨平台优势,使得在不同操作系统上运行代码变得更加方便。 ... [详细]
  • 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件
    本文旨在全面介绍Windows内存管理机制及C++内存分配实例中的内存映射文件。通过对内存映射文件的使用场合和与虚拟内存的区别进行解析,帮助读者更好地理解操作系统的内存管理机制。同时,本文还提供了相关章节的链接,方便读者深入学习Windows内存管理及C++内存分配实例的其他内容。 ... [详细]
  • 本文介绍了200个经典c语言源代码,包括函数的使用,如sqrt函数、clanguagefunct等。这些源代码可以帮助读者更好地理解c语言的编程方法,并提供了实际应用的示例。 ... [详细]
  • 本文讲述了作者从最初对软件工程的选择迷茫到逐渐喜欢并坚持学习的经历。作者在大学期间通过学习专业课和参与项目开发,不断挑战自己并取得成就感。虽然曾考虑过转专业和复读,但最终决定坚持学习软件工程,并为自己的未来努力奋斗。作者还提到了大学生活与自己最初的预期不同,但对此并没有太多抱怨。 ... [详细]
  • 本文介绍了GTK+中的GObject对象系统,该系统是基于GLib和C语言完成的面向对象的框架,提供了灵活、可扩展且易于映射到其他语言的特性。其中最重要的是GType,它是GLib运行时类型认证和管理系统的基础,通过注册和管理基本数据类型、用户定义对象和界面类型来实现对象的继承。文章详细解释了GObject系统中对象的三个部分:唯一的ID标识、类结构和实例结构。 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
author-avatar
江西花而美
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有