2017-04-13 79 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'