SQL NOT IN不起作用


74

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

以下SQL语句不起作用:

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

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

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


您确定您有完全不在foreignStockId中的stock.IdStock吗?
CloudyMarble

您是否真的有任何Inventory不在的物品Subset
Albin Sunnanbo 2011年

1
说明查询应返回的内容。当前,它返回子集中没有商品的所有库存商品。
Stefan Steinegger,

Answers:


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

可能会传回NULL

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) 

或改用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) 

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

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

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

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

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

True AND True AND UnknownUnknown根据真值表评估三个有价值的逻辑

以下链接对各种选项的性能进行了其他讨论。


这为我解决了。选择*从x其中xy不存在(选择不同的ISNULL(c,0))
太空人

哦,天哪,确实select返回了null,并且NOT IN不能正常工作。6年后,我向您致敬
2010年

4

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


0

您还可以使用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 

此语法可在SQL Server,Oracle和Postgres中使用


0

再加上我的2美分:

我见过的SQL Server,即使切换到时返回错误结果not existsleft join-在损坏的数据库。在所涉及的表上运行DBCC CHECKTABLE,还查看NOT IN查询执行计划并重建所涉及的索引,这应该会有所帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.