简体   繁体   中英

LEFT JOIN and WHERE with NULL values in the result

A simple query gives me user1's relationship with other users:

select u.id, u.name, ur.*
from users u
left join user_relationships ur
on ((ur.source_user_id = 1 and target_user_id = u.id) OR
    (ur.source_user_id = u.id and target_user_id = 1))
where u.id != 1
ORDER BY u.id; 

+----+-------+----------+--------+------+
| id | name  | rel_from | rel_to | type |
+----+-------+----------+--------+------+
|  2 | beta  | 2        | 1      | 2    |
|  3 | gamma | 1        | 3      | 2    |
|  4 | delta | 4        | 1      | 1    |
|  5 | five  | NULL     | NULL   | NULL |
+----+-------+----------+--------+------+

But I only want a list of users with whom the relationship type is not 2 ('delta' and 'five').

I tried some approaches.

-- Approach 1
-- -----------------------------
    where 
    (u.id != 1) AND
    (ur.type != 2)
    -- gives 'delta', not 'five'


-- Approach 2
-- -----------------------------    
left join user_relationships ur
on ((ur.source_user_id = 1 and target_user_id = u.id) OR
    (ur.source_user_id = u.id and target_user_id = 1)) AND 
    (ur.type != 2)
where 
    (u.id != 1)    
ORDER BY u.id;
-- ur.* fields are NULL
-- (all rows, except for 'delta')


-- Approach 3
-- -----------------------------    
where 
    (u.id != 1) AND
    ((ur.type != 2) OR 
    (ur.type IS NULL))
    -- this works, but why ?

(A) Why Approaches 1,2 don't work, but 3 does ?

(B) Is there another (perhaps more elegant) way to achieve the same result ?

Kaya,

When you work with possible null values should use the IS NULL comparative.

So your where could be:

 where 
    (u.id != 1) AND
    (ur.type != 2 OR ur.type IS 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