IN中的子查询不起作用

时间:2016-06-25 17:19:38

标签: sql sql-server

我使用的是TransactSQL(Microsoft SQL Server 2014),这是我的问题所在: 我正在使用标准" Northwind"实践数据库,我想看到一个没有任何产品的类别列表。

首先,我创建了一个新类别,它没有任何产品:

insert into Categories (CategoryName) values ('TestCategory')

然后我写了这个:

  SELECT CategoryName 
  FROM Categories
  WHERE CategoryID NOT IN (select CategoryID from Products)

不幸的是,它什么都没有。

以下是我的理解:
我想找到没有与之相关的产品的类别,所以我使用了 WHERE CategoryID NOT IN (select CategoryID from Products),因为我想将Categories表中的每个CategoryID与我从select CategoryID from Products获得的列表进行比较 - 此列表包含HAS产品的每个类别。所以我认为使用NOT IN应该让我看到没有任何产品的类别。

我希望你理解我想要描述的内容。如果你可以帮忙的话会很棒。

3 个答案:

答案 0 :(得分:2)

Sql适用于三个基于值的逻辑。您的表必须在类别ID列中包含null,这就是为什么它不显示任何内容,将子查询修改为

 SELECT CategoryName 
  FROM Categories
  WHERE CategoryID NOT IN (select CategoryID from Products where catogoryID is not null)

答案 1 :(得分:2)

NOT IN不是一个好的结构。如果子查询中的任何返回值为NULL,则它永远不会返回任何行。解决此问题的一种天真方法是使用WHERE

SELECT CategoryName 
FROM Categories
WHERE CategoryID NOT IN (select CategoryID from Products where CategoryId IS NOT NULL);

更好的解决方法是使用NOT EXISTS

SELECT c.CategoryName 
FROM Categories c
WHERE NOT EXISTS (SELECT 1
                  FROM Products p
                  WHERE p.CategoryID = c.CategoryID 
                 );

这表现得更直观。

请注意,此行为是ANSI标准行为。如果存在NULL值,则引擎不知道列表中是否有c.categoryId。因此,它返回NULL,将其视为false。

答案 2 :(得分:0)

我还找到了另一个解决方案:

select CategoryName from Categories c LEFT OUTER JOIN Products p
ON c.CategoryID = p.CategoryID
where ProductName is null

我认为上面的答案更直观,但我只想展示另一种处理方式。