简体   繁体   中英

MySQL not null in left join condition

My query looks like:

   SELECT * 
     FROM users U 
LEFT JOIN posts P ON P.userId = U.id AND P.userId IS NOT NULL;

Why the query also return result where userId is null ?

I know that for my needs I can use INNER JOIN to get only posts related to user but is so strange that LEFT JOIN support multiple conditions, but not work with NOT NULL conditions.

This is because "posts" does not contain the null-values and hence they can´t be filtered at that stage. The Null-values are only generated trough the join, when the server can´t find a corresponding row on the right table. So just put the not null in the where clause and it will work:

SELECT * FROM users U LEFT JOIN posts P ON P.userId = U.id WHERE userId IS NOT NULL;

(EDIT: You should use an inner join for productive work though, as it is the proper way and will give you much greater performance.)

You can also see all users who don´t have posts by inverting that:

SELECT * FROM users U LEFT JOIN posts P ON P.userId = U.id WHERE userId IS  NULL;

You are outer joining the posts table. This means for every users record that has no match in posts you still get this record with all posts columns null.

So say you have a users record with userid = 5 and there is no posts record with id = 5.

ON P.userId = U.id AND P.userId IS NOT NULL

The two combined conditions are not met (there is no record with userid 5), so you get the users record with all posts columns set to null in your results.

Maybe you are simply looking for an inner join? All users records with their posts data?

This query:

SELECT *
FROM users U LEFT JOIN
     posts P
     ON P.userId = U.id AND P.userId IS NOT NULL;

Returns all rows in the users as well as all columns from posts , regardless of whether or not they match. This is true, regardless of whether the ON clause evaluates to TRUE or FALSE.

What you want is a WHERE . In addition, you should only select the columns from users :

SELECT u.*
FROM users U LEFT JOIN
     posts P
     ON P.userId = U.id 
WHERE P.userId IS NOT NULL;

Note that you can also accomplish this using NOT IN or NOT EXISTS .

Because the LEFT JOIN must return every row from the left table by it's definition. The raw may be augmented with the data of the right table depending on the ON clause evaluation. So the following code must return a row.

select u.*, p.*
from ( 
    select 1 as id 
    ) u
left join (
    -- no data at all
    select 2 as id where 1=2
    ) p on 3 = 4 -- never is true

Try this

SELECT * FROM users U LEFT JOIN posts P ON P.userId = U.id
SELECT * FROM users U LEFT JOIN posts P ON P.userId = U.id where P.userId IS NOT NULL;

IS NOT NULL WITH JOINS

 SELECT * FROM users 
 LEFT JOIN posts ON post.user_id = users.id 
 WHERE user_id IS NOT NULL;

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