简体   繁体   中英

SQL query with NOT IN returning no rows

I have a sql statement as

select t.name, t.company from company t inner join employee e
on t.id = e.emp_id
where t.name not in(select t.name from table1 where t.id='x')

This above query returns no rows.

However, when I remove the sub query, and just use

select t.name, t.company from company t inner join employee e
    on t.id = e.emp_id  

I get the required rows.

Also, the sub query

select t.name from table1 where t.id='x'

gives rows of data when executed by itself. Is my syntax for the NOT IN incorrect?

this is because NOT IN (NULL) is always false

select t.name, t.company from company t inner join employee e
on t.id = e.emp_id
where t.name not in(select null from dual)

would be the same.

Use NOT EXISTS instead:

select t.name, t.company 
from company t 
    join employee e on t.id = e.emp_id
where 
    not exists(select 1 from table1 t2 where t.name = t2.name)
and t.id='x' 

follow up: What's the difference between NOT EXISTS vs. NOT IN vs. LEFT JOIN WHERE IS NULL?

A common cause is NULL values in the subquery. But you have a different problem. Here is your query:

select t.name, t.company
from company t inner join employee e
     on t.id = e.emp_id
where t.name not in(select t.name from table1 where t.id='x')

The t.name in the subquery refers to the "t" for company in the outer query. That is, the query is checking for t.name not in (t.name) -- which is always false. The subquery needs the name from table1 . Using no alias fixes this:

select t.name, t.company
from company t inner join employee e
     on t.id = e.emp_id
where t.name not in(select name from table1 where id='x')

Better yet, use meaningful aliases (ie abbreviations of the table name) everywhere:

select c.name, c.company
from company c inner join employee e
     on c.id = e.emp_id
where c.name not in (select t1.name from table1 t1 where t1.id = 'x')

Not sure why the poster accepted the wrong answer. Yes there is an error in the query, the following should be changed from:

where t.name not in(select t.name from table1

to:

where t.name not in(select t1.name from table1 t1

However once that is done, the user's dilemma is still the same. Using NOT EXISTS is a workaround but avoids the real issue. The real solution is the one that was posted by Taryn , namely to add a filter in the subquery to exclude null values.

I am assuming that you might have null values in table1 . If you have null values in table1 , then you will want to explicitly exclude null in your WHERE NOT IN query:

select t.name, t.company 
from company t 
inner join employee e
  on t.id = e.emp_id
where t.name not in(select name 
                    from table1 
                    where id='x'
                       and name is not null);

You will also see that I removed the t. alias from the WHERE clause query. You are using an alias that is associated with the outer table company . You will either need to change the alias name or remove it.

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