简体   繁体   中英

MySQL LEFT JOIN and WHERE clause

There is structure:

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

And also there are two queries:

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;

2

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

I'm wondering why, as a result of the second query, there is no row, in which there is NULL for content_value.value . After all, the condition reads != '123' .
Who would explain this behavior to me.

Thanks in advance.

In #2, if you change where->and, it gives same results as #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'

This means that the joins are getting applied after the DB engine evaluates your select .. from where .. clause.

A WHERE clause further restricts the rows returned by the join query.

More details - SQL join: where clause vs. on clause

Use IS NOT NULL to compare NULL values because they are simply unknown.

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

A NULL value is never "equal to" or "not equal to" a non-NULL value. SQL provides special "IS NULL" and "IS NOT NULL" operators for comparing to NULL values.

The condition in the WHERE clause of the second query negates the "outerness" of the join, by requiring content_value.value to have a non-NULL value. This renders the result equivalent to an INNER JOIN. (For the rows returned when no matching row is found, all of the columns from content_value will be NULL.)

It seems like you are expecting that condition to be evaluated as if it were written like this:

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

If portability to other DBMS isn't a concern, then we can use the MySQL specific NULL-safe comparison <=> (spaceship) operator, for example:

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

I'm assuming that there is a reason this condition is specified in the WHERE clause rather than the ON clause of the outer join. We can generate a different result if we move the condition from the WHERE clause to the ON clause of the outer join.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM