2017-04-13 1 views
0

Es ist Struktur:MySQL LEFT JOIN und WHERE-Klausel

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

Und auch gibt es zwei Abfragen:

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'; 

Ich frage mich, warum, als Ergebnis der zweiten Abfrage gibt es keine Zeile, in der NULL für content_value.value ist. Immerhin lautet die Bedingung != '123'.
Wer würde mir dieses Verhalten erklären.

Vielen Dank im Voraus.

Antwort

0

Verwenden Sie IS NOT NULL, um NULL-Werte zu vergleichen, da sie einfach unbekannt sind.

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

In # 2, wenn Sie ändern wo-> und gibt es dieselben Ergebnisse wie 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' 

Dies bedeutet, dass die angewendet werden, immer schließt sich, nachdem die DB-Engine Ihre wählen .. von wo .. Klausel auswertet.

Eine WHERE-Klausel schränkt die von der Join-Abfrage zurückgegebenen Zeilen weiter ein.

Weitere Details - SQL join: where clause vs. on clause

0

Ein NULL Wert ist nie "gleich" oder "nicht gleich" ein Nicht-NULL-Wert. SQL stellt spezielle "IS NULL" - und "IS NOT NULL" -Operatoren zum Vergleichen mit NULL-Werten bereit.

Die Bedingung in der WHERE-Klausel der zweiten Abfrage negiert die "Outerness" des Joins, indem content_value.value einen Nicht-NULL-Wert erfordert. Dies macht das Ergebnis äquivalent zu einem INNEREN JOIN. (Für die Zeilen zurückgegeben werden, wenn keine passende Zeile gefunden wird, alle Spalten von content_value NULL sein.)

Es scheint, wie Sie diese Bedingung erwarten bewertet werden, als ob es so geschrieben wurde:

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

Wenn Portabilität auf andere DBMS kein Problem ist, dann können wir den MySQL-spezifischen NULL-safe Vergleich <=> (Raumschiff schiff~~POS=HEADCOMP) Operator verwenden, zum Beispiel:

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

Ich gehe davon aus, dass diese Bedingung in der WHERE-Klausel und nicht in der ON-Klausel des Outer Joins angegeben ist. Wir können ein anderes Ergebnis erzeugen, wenn wir die Bedingung von der WHERE-Klausel in die ON-Klausel des äußeren Joins verschieben.

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