即使你认为自己已对关系型数据库的左连接理解深刻,但我敢打赌,这篇文章肯定能让你学会点东西
在…上子句与在哪里子句的不同一种更好地理解带有在哪里.为空子句的复杂匹配条件的简单方法匹配条件与哪里条件的不同
关于“答向左加入B条件表达式"的一点提醒
在…上条件(“答向左连接B条件表达式"中的开)用来决定如何从B表中检索数据行。
如果B表中没有任何一行数据匹配在…上的条件,将会额外生成一行所有列为空的数据
在匹配阶段在哪里子句的条件都不会被使用。仅在匹配阶段完成以后,在哪里子句条件才会被使用。它将从匹配阶段产生的数据中检索过滤。
让我们看一个LFET连接示例:
关系型数据库创建表` product `(` id ` int(10)unsigned NOT NULL AUTO _ INCREMENT,` amount ` int(10)unsigned DEFAULT NULL,PRIMARY KEY(` id `))ENGINE=MyISAM AUTO _ INCREMENT=5 DEFAULT CHARSET=latin1
关系型数据库创建表` product _ details `(` id ` int(10)unsigned NOT NULL,` weight ` int(10)unsigned DEFAULT NULL,` exist ` int(10)unsigned DEFAULT NULL,PRIMARY KEY(` id `))ENGINE=MyISAM DEFAULT CHARSET=latin1
mysql插入产品(id,数量)值(1,100)、(2,200)、(3,300)、(4,400);查询正常,4行受影响(0.00秒)记录:4个重复项:0个警告:0个
MySQL INSERT INTO product _ details(id、重量、存在)值(2,22,0),(4,44,1),(5,55,0),(6,66,1);查询正常,4行受影响(0.00秒)记录:4个重复项:0个警告:0个
mysql SELECT * FROM product - | id |金额|-| 1 | 100 | | 2 | 200 | | 3 | 300 | | 4 | 400 | - 集合中的四行(0.00秒)
MySQL SELECT * FROM product _ details;-| id | weight | exist |-| 2 | 22 | 0 | | 4 | 44 | 1 | | 5 | 55 | 0 | | 6 | 66 | 1 |-集合中的四行(0.00秒)
MySQL SELECT * FROM product LEFT JOIN product _ details ON(product。id=产品详细信息。id);-| id | amount | id | weight | exist |-| 1 | 100 | NULL | NULL | NULL | | 2 | 200 | 2 | 22 | 0 | | 3 | 300 | NULL | NULL | NULL | | 4 | 400 | 4 | 44 | 1 |-集合中的四行(0.00秒)
在…上子句和在哪里子句有什么不同?
一个问题:下面两个查询的结果集有什么不同么?
1.SELECT * FROM product LEFT JOIN product _ details ON(product。id=产品详细信息。id)和产品详细信息。id=2;2.SELECT * FROM product LEFT JOIN product _ details ON(product。id=产品详细信息。id)其中产品_详情。id=2;
用例子来理解最好不过了:
MySQL SELECT * FROM product LEFT JOIN product _ details ON(product。id=产品详细信息。id)和产品_详情。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 |-集合中的四行(0.00秒)
MySQL SELECT * FROM product LEFT JOIN product _ details ON(product。id=产品详细信息。id)其中产品_详情。id=2;- - - | id |金额| id |重量|存在| - | 2 | 200 | 2 | 22 | 0 | - 集合中的一行(0.01秒)
第一条查询使用在…上条件决定了从左连接的产品_详情表中检索符合的所有数据行。
第二条查询做了简单的左连接,然后使用在哪里子句从左连接的数据中过滤掉不符合条件的数据行。
再来看一些示例:
MySQL MySQL SELECT * FROM product LEFT JOIN product _ details ON product。id=产品详细信息。身份证明(identification)和product . amount=100-| id | amount | id | weight | exist |-| 1 | 100 | NULL | NULL | NULL | | 2 | 200 | NULL | NULL | NULL | | 3 | 300 | NULL | NULL | NULL | | NULL | | 4 | 400 | NULL | NULL | NULL |-集合中的四行(0.00秒)
所有来自产品表的数据行都被检索到了,但没有在产品_详情表中匹配到记录(product.id=产品详细信息. id和产品数量=100条件并没有匹配到任何数据)
MySQL SELECT * FROM product LEFT JOIN product _ details ON(product。id=产品详细信息。id)和product . amount=200-| 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 |-集合中的四行(0.01秒)
同样,所有来自产品表的数据行都被检索到了,有一条数据匹配到了。
使用在哪里.为空子句的左连接
当你使用在哪里.为空子句时会发生什么呢?
如前所述,在哪里条件查询发生在匹配阶段之后,这意味着在哪里.为空子句将从匹配阶段后的数据中过滤掉不满足匹配条件的数据行。
纸面上看起来很清楚,但是当你在在…上子句中使用多个条件时就会感到困惑了。
我总结了一种简单的方式来理解上述情况:
将为空作为否定匹配条件使用!(一)和B)==!a或者!B逻辑判断
看看下面的示例:
MySQL SELECT a . * FROM product a LEFT JOIN product _ details b ON a . id=b . id和b .体重!=44且b .存在=0,其中身份证为空;- | id |金额|-| 1 | 100 | | 3 | 300 | | 4 | 400 | - 集合中的3行(0.00秒)
让我们检查一下在…上匹配子句:
(a.id=b.id)和(b .重量!=44)和(b.exist=0)
我们可以把为空子句看作是否定匹配条件。
这意味着我们将检索到以下行:
!(存在(b.id等于a.id)和b .体重!=44且b.exist=0)!存在(b.id等于a.id) ||!(b。重量!=44) || !(b.exist=0)!存在(b.id等于a.id) || b.weight=44 || b.exist=1
就像在C语言中的逻辑和和逻辑运筹学表达式一样,其操作数是从左到右求值的。如果第一个参数做够判断操作结果,那么第二个参数便不会被计算求值(短路效果)
看看别的示例:
MySQL SELECT a . * FROM product a LEFT JOIN product _ details b ON a . id=b . id和b .体重!=44且b .存在=1,其中身份证为空;- | id |金额|-| 1 | 100 | | 2 | 200 | | 3 | 300 | | 4 | 400 | - 集合中的四行(0.00秒)
匹配条件与哪里条件之战
如果你吧基本的查询条件放在在…上子句中,把剩下的否定条件放在在哪里子句中,那么你会获得相同的结果。
例如,你可以不这样写:
SELECT a . * FROM product a LEFT JOIN product _ details bON a . id=b . id和b .体重!=44且b.exist=,其中身份证为空;
你可以这样写:
SELECT a . * FROM product a LEFT JOIN product _ details bON a . id=b . id其中b .身份证为空或重量=44或b .存在=1;
MySQL SELECT a . * FROM product a LEFT JOIN product _ details b ON a . id=b . id其中b .身份证为空或者重量=44或者b .存在=1;- | id |金额|-| 1 | 100 | | 3 | 300 | | 4 | 400 | - 集合中的3行(0.00秒)
你可以不这样写:
SELECT a . * FROM product a LEFT JOIN product _ details bON a . id=b . id和b .体重!=44和乙。存在!=0,其中身份证为空;
可以这样写:
SELECT a . * FROM product a LEFT JOIN product _ details bON a . id=b . id其中b .身份证为空或重量=44或b .存在=0;
MySQL SELECT a . * FROM product a LEFT JOIN product _ details b ON a . id=b . id其中b .身份证为空或者重量=44或者b .存在=0;- | id |金额|-| 1 | 100 | | 2 | 200 | | 3 | 300 | | 4 | 400 | - 集合中的四行(0.00秒)
这些查询真的效果一样?
如果你只需要第一个表中的数据的话,这些查询会返回相同的结果集。有一种情况就是,如果你从左连接的表中检索数据时,查询的结果就不同了。
如前所属,在哪里子句是在匹配阶段之后用来过滤的。
例如:
MySQL SELECT * FROM product a LEFT JOIN product _ details b ON a . id=b . id和b .体重!=44且b .存在=1,其中身份证为空;-| id | amount | id | weight | exist |-| 1 | 100 | NULL | NULL | NULL | | 2 | 200 | NULL | NULL | NULL | | 3 | 300 | NULL | NULL | NULL | | NULL | | NULL | | 4 | 400 | NULL | NULL | NULL |-集合中的四行(0.00秒)
MySQL SELECT * FROM product a LEFT JOIN product _ details b ON a . id=b . id其中b .身份证为空或者重量=44或者b .存在=0;-| id | amount | id | weight | exist |-| 1 | 100 | NULL | NULL | NULL | | 2 | 200 | 2 | 22 | 0 | | 3 | 300 | NULL | NULL | NULL | | 4 | 400 | 4 | 44 | 1 |-集合中的四行(0.00秒)
总附注:
如果你使用左连接来寻找在一些表中不存在的记录,你需要做下面的测试:在哪里部分的列名为空(其中列名列被定义为非空)、MYSQL在查询到一条匹配左连接条件后将停止搜索更多行(在一个特定的组合键下)。