SQL中 EXCEPT、INTERSECT用法

本文介绍了SQL中的集合运算符EXCEPT、INTERSECT和UNION的使用方法及语法限制条件。通过实例展示了如何找出两个表之间的差集、交集和并集。适用于数据库管理和数据处理的相关工作。

EXCEPT 返回两个结果集的差(即从左查询中返回右查询没有找到的所有非重复值)。

INTERSECT 返回 两个结果集的交集(即两个查询都返回的所有非重复值)。

UNION返回两个结果集的并集。

语法:

{ (<SQL-查询语句1>) }
{ EXCEPT | INTERSECT }
{ (<SQL-查询语句2> )}

限制条件

  • (1)所有查询中的列数和列的顺序必须相同。
  • (2)比较的两个查询结果集中的列数据类型可以不同但必须兼容。
  • (3)比较的两个查询结果集中不能包含不可比较的数据类型(xml、text、ntext、image 或非二进制 CLR 用户定义类型)的列。
  • (4)返回的结果集的列名与操作数左侧的查询返回的列名相同。ORDER BY 子句中的列名或别名必须引用左侧查询返回的列名。
  • (5)不能与 COMPUTE 和 COMPUTE BY 子句一起使用。
  • (6)通过比较行来确定非重复值时,两个 NULL 值被视为相等。(EXCEPT 或 INTERSECT 返回的结果集中的任何列的为空性与操作数左侧的查询返回的对应列的为空性相同。)

与表达式中的其他运算符一起使用时的执行顺序

  1. 1、括号中的表达式
  2. 2、INTERSECT 操作数
  3. 3、基于在表达式中的位置从左到右求值的 EXCEPT 和 UNION

如果 EXCEPT 或 INTERSECT 用于比较两个以上的查询集,则数据类型转换是通过一次比较两个查询来确定的,并遵循前面提到的表达式求值规则。

举例:

tableA tableB

NULLNULL
NULL
 
 
:(SELECT * FROM TableA) EXCEPT (SELECT * FROM TableB)
结果: 1
(1 row(s) affected)
B: SELECT * FROM TableA INTERSECT SELECT * FROM TableB
结果:2
   3
   4
   5
    (4 row(s) affected)
<think>我们正在讨论SQL中的EXCEPT子句,根据用户提供的引用内容,EXCEPT用于返回第一个查询结果中不在第二个查询结果中的记录(差集)。注意,MySQL不支持EXCEPT,但SQL Server等支持。 引用[1]提供了基本语法和说明,引用[3]给出了具体示例,引用[2]和[4]提到了EXISTS和INTERSECT,但我们的重点是EXCEPT。 我将按照以下结构组织回答: 1. EXCEPT子句的作用和基本语法 2. 使用规则和注意事项(如两个查询的列数和数据类型必须兼容) 3. 具体示例(参考引用中的例子,并适当扩展) 4. 与NOT EXISTS和LEFT JOIN的对比(根据引用[4]提到的EXISTS,可以简要对比) 5. 生成相关问题 注意:用户要求用中文回答,并且要求生成相关问题。</think>### SQL中`EXCEPT`子句的用法详解 `EXCEPT`是SQL中用于获取两个查询结果**差集**的运算符,返回第一个查询结果中存在但第二个查询结果中不存在的记录。以下是核心用法和示例: --- #### 1. **基本语法** ```sql SELECT 列1, 列2, ... FROM 表1 WHERE 条件 EXCEPT -- 或 EXCEPT ALL SELECT 列1, 列2, ... FROM 表2 WHERE 条件; ``` - **规则**: - 两个`SELECT`语句的列数、数据类型和顺序必须一致。 - 默认去重(`EXCEPT DISTINCT`),使用`EXCEPT ALL`保留重复项。 - MySQL不支持`EXCEPT`,可用`NOT EXISTS`或`LEFT JOIN`替代[^1][^3]。 --- #### 2. **典型应用场景** ##### (1) 查找缺失记录 ```sql -- 找出在表A但不在表B的记录 SELECT id, name FROM employees EXCEPT SELECT id, name FROM resigned_employees; ``` 结果:返回在职员工名单(排除已离职员工)。 ##### (2) 获取次大/次小值(分页查询) ```sql -- 查找第二高分(引用[3]示例) SELECT MAX(score) FROM ( SELECT score FROM exam_results EXCEPT SELECT MAX(score) FROM exam_results -- 排除最高分 ) AS subquery; ``` 结果:返回最高分之外的次高分。 --- #### 3. **与`NOT EXISTS`和`LEFT JOIN`的对比** | 方法 | 特点 | 示例片段 | |---------------|----------------------------------------------------------------------|--------------------------------------------------------------------------| | **`EXCEPT`** | 语法简洁,自动处理列匹配 | `SELECT a,b FROM t1 EXCEPT SELECT a,b FROM t2` | | **`NOT EXISTS`** | 需手动关联表,性能更优[^4] | `SELECT a,b FROM t1 WHERE NOT EXISTS (SELECT 1 FROM t2 WHERE t2.a=t1.a)` | | **`LEFT JOIN`** | 显式控制连接条件,可返回更多字段 | `SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.a=t2.a WHERE t2.a IS NULL` | --- #### 4. **注意事项** 1. **兼容性**: - SQL Server、PostgreSQL支持`EXCEPT`,MySQL需用替代方案[^1][^3]。 2. **去重行为**: - `EXCEPT`默认去重(类似`UNION`),加`ALL`保留重复行: ```sql SELECT name FROM table1 EXCEPT ALL -- 保留重复项 SELECT name FROM table2; ``` 3. **性能优化**: - 对`WHERE`条件列建索引,避免全表扫描。 - 大数据集优先用`NOT EXISTS`(引用[4]提到其效率更高)[^4]。 --- ### 示例扩展 ```sql -- 查找未完成订单的商品(假设orders表有完成状态) SELECT product_id FROM products EXCEPT SELECT product_id FROM orders WHERE status = 'completed'; ``` 结果:返回所有未被成功购买的商品ID。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值