intersect用于返回两个select结果的交集,要求列数、数据类型及顺序严格一致,自动去重并按第一列升序排序,列名以左侧查询为准,null视为相等,不支持直接order by需外层包装。

INTERSECT 能正确返回两个结果集的公共行,但要求列数、数据类型和顺序必须严格一致,否则直接报错。
INTERSECT 的基本用法和隐含约束
Oracle 的 INTERSECT 不是连接操作,而是集合运算符,它自动去重并按第一列升序排序结果。你不能在 INTERSECT 后加 ORDER BY 直接作用于整个查询(除非用子查询或外层包装)。
- 左右两个
SELECT必须有相同数量的列 - 对应位置的列需兼容(如
NUMBER和INTEGER可以,但VARCHAR2(10)和CLOB通常不行) - 列名以左侧查询为准,右侧列名被忽略
-
NULL值会被当作相等处理(即两行都含NULL在同一列,算作匹配)
常见错误:ORA-01789 和列不匹配问题
典型报错 ORA-01789: query block has incorrect number of result columns 就是因为左右列数不等。比如:
SELECT emp_id, dept_id FROM employees INTERSECT SELECT dept_id FROM departments;
这会立刻失败。修复方式只有补全列或对齐结构:
- 补列(用
NULL占位):SELECT emp_id, dept_id FROM employees INTERSECT SELECT NULL, dept_id FROM departments - 或者改写为语义等价的
INNER JOIN+DISTINCT,当列对齐困难时更可控
性能与替代方案对比
INTERSECT 内部通常走哈希或排序合并,对大表可能比等值 JOIN 慢,尤其当没索引支撑时。它还会强制去重,如果你明确知道数据无重复,反而多了一层开销。
- 想保留重复?
INTERSECT不行,得用IN或EXISTS配合子查询 - 要控制排序?必须包一层:
SELECT * FROM (SELECT ... INTERSECT SELECT ...) ORDER BY ... - 跨库或跨版本迁移时注意:MySQL 不支持
INTERSECT,PG 支持但行为略有差异(如对NULL处理)
真正容易被忽略的是列顺序——哪怕两列语义完全一样,只要位置错开,INTERSECT 就不会匹配。写完务必手动核对左右 SELECT 的列序和类型,别依赖“看起来一样”。











