简体   繁体   中英

How to get entries from tableA which have no entry in tableB? (SQL)

In mysql I have tableA with rows userid and valueA and tableB with userid and valueB .

Now I want all entries from tableA which don't have an entry in tableB with the same userid .

I tried several things but can't figure out what I do wrong.

SELECT * FROM `tableA`
left join `tableB` on `tableA`.`userid` = `tableB`.`userid`

This is a very good start actually. It gives me all entries from tableA + the corresponding values from tableB . If they don't exist they are displayed as NULL (in phpmyadmin).

SELECT * FROM `tableA`
left join `tableB` on `tableA`.`userid` = `tableB`.`userid`
where `tableB`.`valueB` = NULL

Too bad, empty result. Maybe this would have been too easy. (By the way: tableA has ~10k entries and tableB has ~7k entries with userid being unique in each. No way the result would be empty if it would do what I want it to do)

SELECT * FROM `tableA`
left join `tableB` on `tableA`.`userid` = `tableB`.`userid`
where `tableA`.`userid` != `tableB`.`userid`

This doesn't work either, and to be honest it also looks totally paradox. Anyways, I'm clueless now. Why didn't my 2nd query work and what is a correct solution?

You are almost there. That second query is SO close! All it needs is one little tweak:

Instead of " = NULL " you need an " IS NULL " in the predicate.

SELECT * FROM `tableA`
left join `tableB` on `tableA`.`userid` = `tableB`.`userid`
where `tableB`.`valueB` IS NULL
                        ^^

Note that the equality comparison operator = will return NULL (rather than TRUE or FALSE) when one side (or both sides) of the comparison are NULL. (In terms of relational databases and SQL, boolean logic has three values, rather than two: TRUE, FALSE and NULL.)

BTW... the pattern in your query, the outer join with the test for the NULL on the outer joined table) is commonly referred to as an "anti-join" pattern. The usual pattern is to test the same column (or columns) that were referred to in the JOIN condition, or a column that has a NOT NULL constraint, to avoid ambiguous results. (for example, what if 'ValueB' can have a NULL value, and we did match a row. Nothing wrong with that at all, it just depends on whether you want that row returned or not.)

If you are looking for rows in tableA that do NOT have a matching row in tableB, we'd generally do this:

SELECT * FROM `tableA`
left join `tableB` on `tableA`.`userid` = `tableB`.`userid`
where `tableB`.`userid` IS NULL
                ^^^^^^  ^^

Note that the IS NULL test is on the userid column, which is guaranteed to be "not null" if a matching rows was found. (If the column had been NULL, the row would not have satisfied the equality test in the JOIN predicate.

Change = NULL for IS NULL on your code. You can also use NOT EXISTS instead:

SELECT * 
FROM `tableA` A
WHERE NOT EXISTS (SELECT 1 FROM `tableB`
                  WHERE `userid` = A.`userid`)

this will help explain the use of working with NULL values:

http://dev.mysql.com/doc/refman/5.0/en/working-with-null.html

the less expensive query would be this, all the other queries sugested are too expensive if the database is too big:

SELECT * FROM tableA a 
   WHERE a.userid NOT IN
     (SELECT  b.user_id FROM tableB b);

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