Reputation: 11295
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.
Upvotes: 0
Views: 16092
Reputation: 42
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;
Upvotes: -1
Reputation: 22811
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
Upvotes: 0
Reputation: 426
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;
Upvotes: 9
Reputation: 1270873
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
.
Upvotes: 0
Reputation: 95080
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?
Upvotes: 0