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
SQL NOT IN not working
提问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 IN
query will not return any rows if any NULL
s exists in the list of NOT IN
values. You can explicitly exclude them using IS NOT NULL
as 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 EXISTS
instead.
或者改写使用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 EXISTS
is 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 中使用的 三值逻辑。谓词可以计算为True
,False
或Unknown
。
A WHERE
clause must evaluate to True
in order for the row to be returned but this is not possible with NOT IN
when NULL
is 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 Unknown
evaluates to Unknown
per 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