我使用的是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应该让我看到没有任何产品的类别。
我希望你理解我想要描述的内容。如果你可以帮忙的话会很棒。
答案 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
我认为上面的答案更直观,但我只想展示另一种处理方式。