为何使用 NOT IN?
之所以聚焦 NOT IN 运算符,是因为它在数据排除场景中非常实用。无论您是在清洗数据、编写报告,还是进行复杂分析,掌握如何有效排除特定数据点都极具价值。该运算符语法直观,但也伴随一些可能影响性能与准确性的细微差别。
我们决定深入探讨 NOT IN,是为了帮助您全面理解并能在 SQL 查询中高效使用它。
理解 SQL NOT IN
NOT IN 的基础
NOT IN 运算符用于 WHERE 子句中,排除某列的值与给定值列表任一项匹配的行。其基本语法如下:
SELECT column_names
FROM table_name
WHERE column_name NOT IN (value1, value2, ...);
该语法突出了运算符在数据筛选中的作用——这是数据分析与数据库管理中的关键一步。
NOT IN 的实际应用
设想一个包含客户信息的数据库表。如果您希望选出不来自特定城市的客户,NOT IN 就能发挥作用,轻松将这些城市从结果集中排除。
循序渐进的 NOT IN 示例
示例 1:排除特定值
假设有一张名为 Customers 的表,包含 CustomerID、CustomerName 和 City 三列。要查找不位于 “New York” 或 “Los Angeles” 的客户,查询如下:
|
CustomerlD |
CustomerName |
City |
|
1 |
John Doe |
New York |
|
2 |
Jane Smith |
Los Angeles |
|
3 |
Emily Jones |
Chicago |
|
4 |
Chris Brown |
Miami |
|
5 |
Alex Johnson |
San Francisco |
|
6 |
Jessica White |
New York |
Customers 表
SELECT CustomerName, City
FROM Customers
WHERE City NOT IN ('New York', 'Los Angeles');
|
CustomerName |
City |
|
Emily Jones |
Chicago |
|
Chris Brown |
Miami |
|
Alex Johnson |
San Francisco |
示例 2:结合子查询使用 NOT IN
NOT IN 也可与子查询配合使用。例如,查找尚未被下单的产品:
|
ProductID |
ProductName |
|
1 |
Apple |
|
2 |
Banana |
|
3 |
Orange |
|
4 |
Pear |
|
5 |
Grape |
Products 表
|
OrderID |
ProductID |
|
101 |
2 |
|
102 |
4 |
|
103 |
2 |
|
104 |
3 |
Orders 表
SELECT ProductName
FROM Products
WHERE ProductID NOT IN (
SELECT ProductID
FROM Orders
);
|
ProductName |
|
Apple |
|
Grape |
常见陷阱与规避方法
处理 NULL 值
当值列表包含 NULL 时,NOT IN 常会出问题。由于 NULL 表示未知值,与 NULL 的任何比较在使用 NOT IN 时都不会返回任何行,即便逻辑上应当排除的行也会被影响。
为避免此问题,应确保值列表不包含 NULL,或使用 NOT EXISTS 等替代方案。
示例:
假设有一张 Orders 表,包含 CustomerID 列,其中部分为 NULL 代表游客订单。如果您运行查询以查找不由某些客户下的订单,并将 NULL 包含在列表中,将导致无结果返回。
|
OrderID |
CustomerID |
|
101 |
3 |
|
102 |
4 |
|
103 |
2 |
|
104 | |
|
106 |
1 |
Orders 表
-- Assume we want to exclude CustomerID 1, 2, and unknown (NULL) customers
SELECT OrderID
FROM Orders
WHERE CustomerID NOT IN (1, 2, NULL);
此查询将不返回任何行,这很可能并非预期结果。
解决方案: 为确保结果准确,请勿在 NOT IN 的列表中包含 NULL。或者,将已知值的 NOT IN 与 IS NOT NULL 结合使用,以妥善处理 NULL。
SELECT OrderID
FROM Orders
WHERE CustomerID NOT IN (1, 2) AND CustomerID IS NOT NULL;
|
OrderID |
|
101 |
|
102 |
性能考量
对于大型数据集或子查询,NOT IN 可能不如 NOT EXISTS 或 LEFT JOIN /IS NULL 等替代方式高效。低效之处在于 NOT IN 需要将表中每一行与列表中的每个值进行比较,这在大数据量时可能显著拖慢性能。
SQL NOT IN 的替代方案
使用 NOT EXISTS
在处理可能返回 NULL 值的子查询时,通常推荐使用 NOT EXISTS 替代 NOT IN。它通常更高效,因为一旦找到匹配就会停止。
示例:
查找尚未被下单的产品,使用 NOT EXISTS:
SELECT ProductName
FROM Products p
WHERE NOT EXISTS (
SELECT 1
FROM Orders o
WHERE o.ProductID = p.ProductID
);
|
ProductName |
|
Apple |
|
Grape |
该查询检查订单表中是否不存在某产品记录,相比用 NOT IN 对着可能很长的 ID 列表比较,往往更高效。
LEFT JOIN / IS NULL
另一种排除行的高效方式是将 LEFT JOIN 与 WHERE ... IS NULL 结合使用。此方法对大型数据集尤其有效。
示例:
实现同样的目标——查找尚未被下单的产品:
SELECT p.ProductName
FROM Products p
LEFT JOIN Orders o ON p.ProductID = o.ProductID
WHERE o.ProductID IS NULL;
|
ProductName |
|
Apple |
|
Grape |
该方法利用 LEFT JOIN 保留所有产品及其匹配的订单,再通过 WHERE o.ProductID IS NULL 过滤掉有订单的产品,从而实现排除。
使用 NOT IN 的最佳实践
- 检查列表中的
NULL值:确保用于NOT IN的列表不包含 NULL,以避免意外结果。 - 考虑数据集大小:对于大型数据集或子查询,评估
NOT EXISTS等替代方案是否能提供更佳性能。 - 索引:尽可能为
NOT IN子句涉及的列创建索引,以提升查询性能。
在真实数据项目中使用 NOT IN
在数据分析中,SQL 的 “Not IN” 命令常用于检索特定数据。本节我们使用一家书店的数据库,跟踪其库存(店内可售图书)与销售(已售出图书)。我们的目标是识别哪些书从未售出。
我们有两张表:
- Inventory:存储书店内图书的信息。
- Sales:存储已售出图书的记录。

Inventory 表

Sales 表
现在,我们要找出哪些书从未售出。
SELECT Title, Author
FROM Inventory
WHERE BookID NOT IN (
SELECT BookID
FROM Sales
);

接下来,我们希望识别库存中在上个月未售出的图书,假设今天是 2024 年 2 月 7 日。这需要将 Sales 表中的 SaleDate 与当前日期进行比对。
SELECT Title, Author
FROM Inventory
WHERE BookID NOT IN (
SELECT BookID
FROM Sales
WHERE SaleDate >= date('now', '-1 month')
);

结论
NOT IN 运算符是 SQL 中用于从查询结果中排除特定值的多面手。通过理解其语法、应用场景与潜在陷阱,您就能在数据处理任务中有效地使用它。
请务必考虑 NULL 值与数据集规模,以优化查询的性能与准确性。随着您对 NOT IN 的熟悉,它将成为您 SQL 工具箱中的得力助手,助您更精准高效地开展数据分析与管理。
您可以在我们的 Improving Query Performance in SQL Server 课程中进一步学习 NOT IN 与 NOT EXISTS,并在我们的 SQL Basics Cheat Sheet 与 SQL Fundamentals skill track 中探索更多 SQL 运算符与相关内容。
作为一名持证的数据科学家,我热衷于利用前沿技术打造创新的机器学习应用。凭借在语音识别、数据分析与报告、MLOps、对话式人工智能以及自然语言处理方面的扎实背景,我不断打磨构建智能系统的能力,力求带来切实影响。除技术专长外,我也擅长沟通,能够将复杂概念提炼为清晰、简明的表述。因此,我成为数据科学领域备受关注的博主,与不断壮大的数据专业人士社区分享洞见与实践经验。目前,我专注于内容创作与编辑,借助大语言模型打造有力且吸引人的内容,帮助企业与个人更好地发挥数据价值。

在数据分析与管理领域,SQL(结构化查询语言)是访问与操作数据库系统的关键工具。在其众多功能中,
NOT IN运算符可用于强力筛选数据集,帮助用户排除与特定值列表匹配的行。本文面向初学者与数据从业者,旨在消除使用NOT IN的疑惑,确保理解其用法并认识其潜在陷阱。