msyqlleftjoinon后面多个条件(二)

2014-11-24 15:43:42 · 作者: · 浏览: 3
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 WHER