2017-04-13 86 views
0

有结构:的MySQL LEFT JOIN和WHERE子句

CREATE TABLE `contents` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT, 
`title` VARCHAR(45) NULL, 
PRIMARY KEY (`id`)); 

CREATE TABLE `content_values` (
`content_id` INT UNSIGNED NOT NULL, 
`field_id` INT UNSIGNED NOT NULL, 
`value` VARCHAR(45) NULL, 
PRIMARY KEY (`content_id`, `field_id`)); 

INSERT INTO `contents` VALUES (1,'test-title-1'),(2,'test-title-2'); 
INSERT INTO `content_values` VALUES (1,4,'test-value'); 

http://sqlfiddle.com/#!9/028d0/5

而且也有两个疑问:

select contents.*, content_values.value 
from contents 
left join content_values on content_values.content_id=contents.id and 
content_values.field_id = 4; 
select contents.*, content_values.value 
from contents 
left join content_values on content_values.content_id=contents.id and 
content_values.field_id = 4 
where content_values.value != '123'; 

我想知道为什么,作为第二个查询的结果,没有行,其中有NULLcontent_value.value。毕竟,条件为!= '123'
谁会向我解释这种行为。

在此先感谢。

回答

0

使用IS NOT NULL来比较NULL值,因为它们只是未知的。

select contents.*, content_values.value 
from contents 
LEFT join content_values 
on content_values.content_id=contents.id and content_values.field_id=4 
where content_values.value IS NULL OR content_values.value != '123'; 

Working with null values

0

在#2,如果你改变,而─>和,它提供了相同的结果,#1。

select contents.*, content_values.value 
from contents 
left join content_values on content_values.content_id=contents.id and content_values.field_id=4 
**and** content_values.value != '123' 

这意味着加入越来越应用于数据库引擎评估你的 选择..从那里..子句之后。

WHERE子句进一步限制连接查询返回的行。

更多细节 - SQL join: where clause vs. on clause

0

NULL值从不“等于”或“不等于”非空值。 SQL提供了特殊的“IS NULL”和“IS NOT NULL”运算符来与NULL值进行比较。

第二个查询的WHERE子句中的条件通过要求content_value.value具有非NULL值来抵消连接的“外部”。这使得结果等同于INNER JOIN。 (对于行返回时,没有找到匹配的行,所有列从content_value将是NULL。)

好像你正期待就好像它是这样写的,以评估该条件:

where (content_values.value IS NULL OR content_values.value != '123') 

如果移植到其他DBMS不是问题,那么我们就可以使用MySQL的具体NULL安全比较<=>(飞船)运算符,例如:

where NOT (content_values.value <=> '123') 

我假设在WHERE子句中指定了这个条件,而不是外连接的ON子句。如果将条件从WHERE子句移动到外部联接的ON子句,我们可以生成不同的结果。

ON content_values.content_id = contents.id 
AND content_values.field_id = 4 
AND content_values.value  != '123'