SQL NOT IN 不工作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5231712/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-01 09:36:58  来源:igfitidea点击:

SQL NOT IN not working

sqlsql-server

提问by Sam

I have two databases, one which holds the inventory, and another which contains a subset of the records of the primary database.

我有两个数据库,一个保存库存,另一个包含主数据库记录的子集。

The following SQL statement is not working:

以下 SQL 语句不起作用:

SELECT  stock.IdStock
        ,stock.Descr       
FROM    [Inventory].[dbo].[Stock] stock
WHERE   stock.IdStock NOT IN
        (SELECT foreignStockId FROM
         [Subset].[dbo].[Products])

The not in does not work. Removing the NOT gives the correct results, i.e. products that are in both databases. However, using the NOT IN is not returning ANY results at all.

not in 不起作用。删除 NOT 会给出正确的结果,即两个数据库中的产品。但是,使用 NOT IN 根本不会返回任何结果。

What am I doing wrong, any ideas?

我做错了什么,有什么想法吗?

回答by Martin Smith

SELECT foreignStockId
FROM   [Subset].[dbo].[Products]  

Probably returns a NULL.

可能返回一个NULL.

A NOT INquery will not return any rows if any NULLs exists in the list of NOT INvalues. You can explicitly exclude them using IS NOT NULLas below.

NOT IN如有查询将不会返回任何行NULL中的列表中存在小号NOT IN值。您可以使用IS NOT NULL如下明确排除它们。

SELECT stock.IdStock,
       stock.Descr
FROM   [Inventory].[dbo].[Stock] stock
WHERE  stock.IdStock NOT IN (SELECT foreignStockId
                             FROM   [Subset].[dbo].[Products]
                             WHERE  foreignStockId IS NOT NULL) 

Or rewrite using NOT EXISTSinstead.

或者改写使用NOT EXISTS

SELECT stock.idstock,
       stock.descr
FROM   [Inventory].[dbo].[Stock] stock
WHERE  NOT EXISTS (SELECT *
                   FROM   [Subset].[dbo].[Products] p
                   WHERE  p.foreignstockid = stock.idstock) 

As well as having the semantics that you want the execution plan for NOT EXISTSis often simpler as looked at here.

除了具有您想要的执行计划的语义外,NOT EXISTS通常更简单,如此处所示

The reason for the difference in behaviour is down to the three valued logicused in SQL. Predicates can evaluate to True, False, or Unknown.

行为差异的原因归结为SQL 中使用的 三值逻辑。谓词可以计算为TrueFalseUnknown

A WHEREclause must evaluate to Truein order for the row to be returned but this is not possible with NOT INwhen NULLis present as explained below.

一个WHERE子句必须评估到True为了要返回的行,但这个是不可能的NOT IN,当NULL如下面解释目前是。

'A' NOT IN ('X','Y',NULL)is equivalent to 'A' <> 'X' AND 'A' <> 'Y' AND 'A' <> NULL)

'A' NOT IN ('X','Y',NULL)相当于 'A' <> 'X' AND 'A' <> 'Y' AND 'A' <> NULL)

  • 'A' <> 'X' = True
  • 'A' <> 'Y' = True
  • 'A' <> NULL = Unknown
  • 'A' <> 'X' = True
  • 'A' <> 'Y' = True
  • 'A' <> NULL = Unknown

True AND True AND Unknownevaluates to Unknownper the truth tables for three valued logic.

True AND True AND Unknown计算结果为Unknown三个值逻辑真值表

The following links have some additional discussion about performance of the various options.

以下链接对各种选项的性能进行了一些额外的讨论。

回答by MP?kalski

If NOT INdoes not work, you may always try to do LEFT JOIN. Then filter by WHEREusing one of the values from the joined table, which are NULL. Provided, the value you were joining by does not containany NULLvalue.

如果NOT IN不起作用,您可以始终尝试执行LEFT JOIN。然后使用连接表中的值之一按WHERE进行过滤,这些值是NULL。前提是您加入的值不包含任何NULL值。

回答by Raj Kamal

You can also use Case clause to tackle such issues

您还可以使用 Case 子句来解决此类问题

SELECT  stock.IdStock
        ,stock.Descr        
FROM    [Inventory].[dbo].[Stock] stock
WHERE   (Case when stock.IdStock IN
        (SELECT foreignStockId FROM
        [Subset].[dbo].[Products]) then 1 else 0 end) = 0 

this syntax works in SQL Server, Oracle and postgres

此语法适用于 SQL Server、Oracle 和 postgres