首頁  >  文章  >  資料庫  >  msyqlleftjoinon后面多个条件_MySQL

msyqlleftjoinon后面多个条件_MySQL

WBOY
WBOY原創
2016-06-01 13:26:162282瀏覽

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

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

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

1 1. <code class="sql keyword">SELECT <code class="sql plain">* <code class="sql keyword">FROM <code class="sql plain">product <code class="sql color2">LEFT <code class="sql color1">JOIN <code class="sql plain">product_details 2 <code class="sql keyword">ON <code class="sql plain">(product.id = product_details.id) 3 <code class="sql color1">AND <code class="sql plain">product_details.id=2; 4 2. <code class="sql keyword">SELECT <code class="sql plain">* <code class="sql keyword">FROM <code class="sql plain">product <code class="sql color2">LEFT <code class="sql color1">JOIN <code class="sql plain">product_details 5 <code class="sql keyword">ON <code class="sql plain">(product.id = product_details.id) 6 <code class="sql keyword">WHERE <code class="sql plain">product_details.id=2;

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

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

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

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

再来看一些示例:

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

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

01 mysql> <code class="sql keyword">SELECT <code class="sql plain">* <code class="sql keyword">FROM <code class="sql plain">product <code class="sql color2">LEFT <code class="sql color1">JOIN <code class="sql plain">product_details 02 <code class="sql keyword">ON <code class="sql plain">(product.id = product_details.id) 03 <code class="sql color1">AND <code class="sql plain">product.amount=200; 04 +<code class="sql comments">----+--------+------+--------+-------+ 05 | id | amount | id | weight | exist | 06 +<code class="sql comments">----+--------+------+--------+-------+ 07 | 1 | 100 | <code class="sql color1">NULL <code class="sql plain">| <code class="sql color1">NULL <code class="sql plain">| <code class="sql color1">NULL <code class="sql plain">| 08 | 2 | 200 | 2 | 22 | 0 | 09 | 3 | 300 | <code class="sql color1">NULL <code class="sql plain">| <code class="sql color1">NULL <code class="sql plain">| <code class="sql color1">NULL <code class="sql plain">| 10 | 4 | 400 | <code class="sql color1">NULL <code class="sql plain">| <code class="sql color1">NULL <code class="sql plain">| <code class="sql color1">NULL <code class="sql plain">| 11 +<code class="sql comments">----+--------+------+--------+-------+ 12 4 <code class="sql keyword">rows <code class="sql color1">in <code class="sql keyword">set <code class="sql plain">(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 <code class="sql plain">a.* <code class="sql keyword">FROM <code class="sql plain">product a <code class="sql color2">LEFT <code class="sql color1">JOIN <code class="sql plain">product_details b 02 <code class="sql keyword">ON <code class="sql plain">a.id=b.id <code class="sql color1">AND <code class="sql plain">b.weight!=44 <code class="sql color1">AND <code class="sql plain">b.exist=0 03 <code class="sql keyword">WHERE <code class="sql plain">b.id <code class="sql keyword">IS <code class="sql color1">NULL<code class="sql plain">; 04 +<code class="sql comments">----+--------+ 05 | id | amount | 06 +<code class="sql comments">----+--------+ 07 | 1 | 100 | 08 | 3 | 300 | 09 | 4 | 400 | 10 +<code class="sql comments">----+--------+ 11 3 <code class="sql keyword">rows <code class="sql color1">in <code class="sql keyword">set <code class="sql plain">(0.00 sec)

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

1 (a.id=b.id) <code class="sql color1">AND <code class="sql plain">(b.weight!=44) <code class="sql color1">AND <code class="sql plain">(b.exist=0)

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

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

1 !( exist(b.id that equals <code class="sql keyword">to <code class="sql plain">a.id) <code class="sql color1">AND <code class="sql plain">b.weight !=44 <code class="sql color1">AND <code class="sql plain">b.exist=0 ) 2 !exist(b.id that equals <code class="sql keyword">to <code class="sql plain">a.id) || !(b.weight !=44) || !(b.exist=0) 3 !exist(b.id that equals <code class="sql keyword">to <code class="sql plain">a.id) || b.weight =44 || b.exist=1

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

看看别的示例:

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

Matching-ConditionsWhere-conditions 之战

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

例如,你可以不这样写:

1 SELECT <code class="sql plain">a.* <code class="sql keyword">FROM <code class="sql plain">product a <code class="sql color2">LEFT <code class="sql color1">JOIN <code class="sql plain">product_details b 2 <code class="sql keyword">ON <code class="sql plain">a.id=b.id <code class="sql color1">AND <code class="sql plain">b.weight!=44 <code class="sql color1">AND <code class="sql plain">b.exist=0 3 WHERE <code class="sql plain">b.id <code class="sql keyword">IS <code class="sql color1">NULL<code class="sql plain">;

你可以这样写:

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

你可以不这样写:

1 SELECT <code class="sql plain">a.* <code class="sql keyword">FROM <code class="sql plain">product a <code class="sql color2">LEFT <code class="sql color1">JOIN <code class="sql plain">product_details b 2 ON <code class="sql plain">a.id=b.id AND b.weight!=44 AND b.exist!=0 3 WHERE <code class="sql plain">b.id <code class="sql keyword">IS <code class="sql color1">NULL<code class="sql plain">;

可以这样写:

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

这些查询真的效果一样?

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

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

例如:

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

总附注:

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

bitsCN.com
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn