跳至主要内容

SQL NOT IN 运算符:初学者完整指南

通过本初学者指南掌握 SQL 的 NOT IN 运算符。学习如何高效筛选数据、避免常见陷阱,并了解更高效的替代方案
· 5分钟 阅读

使用 AI 探索

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

为何使用 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:存储已售出图书的记录。

image4.png

Inventory 表

image3.png

Sales 表

现在,我们要找出哪些书从未售出。

SELECT Title, Author 
FROM Inventory 
WHERE BookID NOT IN (
    SELECT BookID 
    FROM Sales
);

image1.png

接下来,我们希望识别库存中在上个月未售出的图书,假设今天是 2024 年 2 月 7 日。这需要将 Sales 表中的 SaleDate 与当前日期进行比对。

SELECT Title, Author 
FROM Inventory 
WHERE BookID NOT IN (
    SELECT BookID 
    FROM Sales
    WHERE SaleDate >= date('now', '-1 month')
);

image2.png

结论

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 运算符与相关内容。

Abid Ali Awan

作者

Abid Ali Awan

作为一名持证的数据科学家,我热衷于利用前沿技术打造创新的机器学习应用。凭借在语音识别、数据分析与报告、MLOps、对话式人工智能以及自然语言处理方面的扎实背景,我不断打磨构建智能系统的能力,力求带来切实影响。除技术专长外,我也擅长沟通,能够将复杂概念提炼为清晰、简明的表述。因此,我成为数据科学领域备受关注的博主,与不断壮大的数据专业人士社区分享洞见与实践经验。目前,我专注于内容创作与编辑,借助大语言模型打造有力且吸引人的内容,帮助企业与个人更好地发挥数据价值。

主题