UNION会隐式去重并可能排序,UNION ALL完全不处理重复;前者执行全行比对和默认排序(因数据库而异),后者仅追加结果;二者均要求列数与类型严格一致,且ORDER BY只能作用于最外层。

UNION 会隐式去重并可能排序,UNION ALL 完全不处理重复
UNION 不是简单拼接结果,它内部执行了类似 DISTINCT 的操作:对全部行做全字段比对,删掉完全重复的记录。有些数据库(如 PostgreSQL、SQL Server)还会在没写 ORDER BY 的情况下对最终结果做默认排序,这不是标准要求,但确实会发生。UNION ALL 则跳过这两步——既不比对重复,也不调整顺序,只是把第二个 SELECT 的结果追加到第一个后面。
列数、数据类型必须严格一致,否则报错
无论用哪个操作符,都强制要求每个 SELECT 的列数相同,且对应位置的列类型兼容。比如第一个 SELECT 返回 INT, VARCHAR(50), DATE,第二个就不能是 TEXT, INT, TIMESTAMP——哪怕只是 VARCHAR 和 TEXT 在某些引擎里能隐式转换,也建议显式 CAST 或保持一致。常见错误信息像 "UNION types text and integer cannot be matched" 就是类型不兼容导致的。
性能差距明显,尤其在大数据量时
UNION 的去重逻辑本质是分组或排序+扫描,时间复杂度通常是 O(n log n) 级别;UNION ALL 是纯追加,接近 O(n)。实测中,合并两个百万行结果集,UNION 可能慢 3–5 倍。如果你能确认源头数据无重复(比如分别查不同状态的订单表),或者业务逻辑本就允许重复(如日志归档合并),直接用 UNION ALL 更稳妥。
ORDER BY 必须放在最后,不能写在单个 SELECT 里
UNION 或 UNION ALL 是集合操作,只接受最外层的 ORDER BY。下面这种写法是错的:
SELECT id FROM t1 ORDER BY id UNION ALL SELECT id FROM t2;
正确写法只能是:
(SELECT id FROM t1) UNION ALL (SELECT id FROM t2) ORDER BY id;
括号不是必须的,但加上更清晰;ORDER BY 作用的是整个合并后的结果集,排序字段必须出现在最外层 SELECT 的列列表中。
实际用的时候,最容易被忽略的是:UNION 的“去重”是基于**整行全字段相等**,而不是某几个业务主键。如果两行只有 ID 相同、其他字段有细微差异(比如时间戳精度不同、空格数量不同),它们不会被当成重复行剔除——这点常导致误以为 UNION 没生效。










