在 2026 年的数据库生态系统中,数据不仅仅是静止的记录,更是流动的资产。在日常的数据库管理和开发工作中,我们经常需要在不同的数据集之间找出差异。比如,你可能想知道“哪些学生选修了课程A但没有选修课程B”,或者“哪些客户在去年有购买记录但今年没有”。这就是集合运算大显身手的时候了。
在这篇文章中,我们将深入探讨 SQL 中的一个强大但有时被忽视的工具:EXCEPT 子句。不同于传统的教程,我们将结合 2026 年最新的开发范式——如 AI 辅助编程和数据工程化实践,带你了解它是如何工作的,它与 NOT IN 有什么本质区别,以及如何在你的日常查询和自动化流水线中高效地使用它。无论你是 SQL 新手还是希望复习基础知识的开发者,这篇文章都将为你提供清晰的见解和实战技巧。
什么是 SQL EXCEPT 子句?
简单来说,EXCEPT 操作符用于返回第一个查询(左边的查询)结果中存在,但在第二个查询(右边的查询)结果中不存在的行。你可以把它想象成数学中的集合差集运算(A – B),或者是数据剔除的过程。
在我们处理大规模数据集(Data Lakes)或进行快速原型开发时,这个操作符非常有用,因为它能够以声明式的方式表达“差异”,而无需编写复杂的过滤逻辑。它的工作原理类似于从一个结果集中“减去”另一个结果集,这在数据清洗和 ETL(抽取、转换、加载)流程中至关重要。
#### EXCEPT 的核心特性
在开始写代码之前,我们需要了解 EXCEPT 的几个关键行为,这将帮助我们避免常见的错误:
- 去重机制:这是 INLINECODE494738e6 最显著的特点之一。它不仅比较数据,还会自动对最终结果进行去重。如果左表中有两行完全相同的数据,且右表中排除了该数据,结果中只会保留一行。这类似于默认执行了 INLINECODE9c73fc2a 操作。
- 列匹配规则:使用 INLINECODE6acd0a00 时,两个 INLINECODEb358533a 语句查询的列数必须相同,且对应列的数据类型必须兼容。数据库引擎无法比较一个字符串列和一个整数列。
- 排序处理:INLINECODEecd34a4d 操作的结果集是无序的。如果你需要特定的排序,必须在查询的最后加上 INLINECODE53f13dd4 子句。
基础语法与结构
让我们先来看看标准的语法结构。这是构建所有复杂查询的基础。
CODEBLOCKbc735f2fINLINECODE4d147372SELECTINLINECODEa890978eEXCEPTINLINECODE5f40f9baINTINLINECODE47c924b1VARCHARINLINECODE2de7c1feStudentsINLINECODEa6347522TeachingAssistantsINLINECODE7d872864AliceINLINECODE9b3e23faBobINLINECODE237cefa0CharlieINLINECODE3b349d9cDavidINLINECODEa96cd1aeAliceINLINECODE2e252e2cAliceINLINECODE25b3720bEveINLINECODEa7951541AliceINLINECODE494ac55dAliceINLINECODE38a8487cBobINLINECODEacd74d8bCharlieINLINECODEbcd36517DavidINLINECODEec597e0aAliceINLINECODE537d276fBobINLINECODEc250c838CharlieINLINECODEd52a2722DavidINLINECODE904f3122LEFT JOIN … WHERE IS NULLINLINECODEfa6083a0EXCEPTINLINECODE50ecbadfEXCEPTINLINECODE39e51e5fEXCEPTINLINECODE8246ea05NOT ININLINECODEa2265f96EXCEPTINLINECODEd3b6ed37NOT ININLINECODE71c676b5NOT ININLINECODEf95ac730NULLINLINECODE4f67a7a5UNKNOWNINLINECODE29f9fd45EXCEPTINLINECODE653a7231NULLINLINECODE27feb189EXCEPTINLINECODE72a0b0baNOT ININLINECODE13a42681LEFT JOININLINECODE0d11bfcdEXCEPTINLINECODE19b26f71TransactionDateINLINECODE7727e943EXCEPTINLINECODE307fe666EXCEPTINLINECODE863b9126EXPLAIN ANALYZEINLINECODE705142e0EXCEPTINLINECODEab150e8eLEFT JOININLINECODE617a7e33NOT EXISTSINLINECODEa78f3c04NOT EXISTSINLINECODE1916a2c4NOT EXISTSINLINECODE095e3792EXCEPTINLINECODE9f32d1b3NOT EXISTSINLINECODEc5678094NOT ININLINECODE910adfafEXCEPTINLINECODE4d61c5d0EXCEPTINLINECODE0d7a4809EXCEPTINLINECODE21227591EXCEPTINLINECODEfa4d3d99INTERSECTINLINECODEc2c30413LEFT JOIN … WHERE … IS NULLINLINECODE164348bfEXCEPTINLINECODE84838d45EXCEPT ALLINLINECODEc4e61a49EXCEPTINLINECODE0854508cEXCEPT ALLINLINECODE33b85bf1EXCEPTINLINECODE6fad7e8eNOT ININLINECODE1bf130dfEXCEPTINLINECODEb11ad5daLEFT JOININLINECODE334ae1aeWHERE NOT IN 子句,用 EXCEPT` 替换它们,并观察生成的执行计划是否有变化。当你能够熟练地在集合运算之间切换时,你的 SQL 编写水平就已经迈上了一个新的台阶,准备好应对 2026 年及以后的数据挑战。
希望这篇文章能帮助你解决实际开发中遇到的差集查询问题!