【问题标题】:SQL query with NOT IN returning no rows带有 NOT IN 的 SQL 查询不返回任何行
【发布时间】:2013-06-17 14:38:33
【问题描述】:

我有一个sql语句

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')

以上查询不返回任何行。

但是,当我删除子查询时,只需使用

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

我得到了所需的行。

还有子查询

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

自行执行时提供数据行。我的 NOT IN 语法不正确吗?

【问题讨论】:

    标签: sql plsql


    【解决方案1】:

    这是因为NOT IN (NULL)总是错误的

    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)
    

    会是一样的。

    改用NOT EXISTS

    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' 
    

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

    【讨论】:

    • t.name not in(t.name) 是这里的问题。这绝不是真的。
    • 这是因为至少有一个 t.name 为空。
    • 你没有抓住重点。即使看不到 NULL,查询也永远不会为真。 3 NOT IN (3) 是假的。
    • 你说得对,他也使用了t. 别名而不是使用其他表别名。你会注意到我也纠正了这一点。
    • 但是这个错字本身就足以导致所描述的问题,那么为什么要明确断言这是因为NOT IN (NULL)
    【解决方案2】:

    一个常见的原因是子查询中的NULL 值。但是你有一个不同的问题。这是您的查询:

    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')
    

    子查询中的t.name 指的是外部查询中company 的“t”。也就是说,查询正在检查t.name not in (t.name)——这总是错误的。子查询需要来自table1name。不使用别名可以解决这个问题:

    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')
    

    更好的是,在任何地方都使用有意义的别名(即表名的缩写):

    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')
    

    【讨论】:

      【解决方案3】:

      不知道为什么发帖人接受了错误的答案。是的,查询中有错误,应更改以下内容:

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

      到:

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

      但是一旦完成,用户的困境仍然是一样的。使用 NOT EXISTS 是一种解决方法,但可以避免真正的问题。真正的解决方案是Taryn 发布的,即在子查询中添加过滤器以排除空值。

      【讨论】:

        【解决方案4】:

        我假设您可能在 table1 中有 null 值。如果您在 table1 中有 null 值,那么您需要在 WHERE NOT IN 查询中明确排除 null

        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);
        

        您还会看到我从WHERE 子句查询中删除了t. 别名。您正在使用与外部表 company 关联的别名。您将需要更改别名或将其删除。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-21
          • 1970-01-01
          • 2017-10-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多