mysql中UNION与UNION ALL的合并查询语法

来源:这里教程网 时间:2026-02-28 20:42:03 作者:

UNION 和 UNION ALL 的核心区别在哪

根本区别在于是否去重:

UNION
会自动去除重复行,
UNION ALL
完全不处理重复,直接拼接结果集。这意味着
UNION
内部隐式执行了
DISTINCT
操作,而
UNION ALL
只是物理追加。

实际影响很直接:

UNION
性能更低,尤其在大数据量时,需排序 + 去重
UNION ALL
几乎无额外开销,执行更快
两者都要求各
SELECT
子句列数相同、对应列类型兼容(MySQL 会尝试隐式转换)
列名以第一个
SELECT
的字段名为准

什么时候必须用 UNION,不能用 UNION ALL

当你明确需要合并后结果唯一时,比如统计多个渠道的用户 ID 且不能重复计数,或拼接不同条件查出的主键集合用于后续

IN
查询 —— 这时若用
UNION ALL
,可能引入重复 ID 导致逻辑错误或性能下降(如子查询中重复值被多次匹配)。

典型场景包括:

多表联合去重取 ID 列表 分页前对多个来源数据统一去重再排序
NOT IN
/
LEFT JOIN ... IS NULL
配合做排除逻辑,重复值会影响结果正确性

ORDER BY 和 LIMIT 在 UNION 中怎么写才合法

ORDER BY
LIMIT
不能出现在单个子查询里(除最外层),否则报错:
ERROR 1221 (HY000): Incorrect usage of UNION and ORDER BY

正确写法是把整个

UNION
当作一个派生表,或直接在最后加
ORDER BY
LIMIT

SELECT id, name FROM t1
UNION ALL
SELECT id, name FROM t2
ORDER BY id DESC
LIMIT 10;

注意:

ORDER BY
中的字段名必须来自第一个
SELECT
的列(或其别名)
如果想对每个子查询单独排序再合并,得用子查询包装:
(SELECT ... ORDER BY x LIMIT n) UNION ALL (SELECT ... ORDER BY y LIMIT m)
LIMIT
放在末尾是对合并后整体生效;若要限制每个子查询,必须加括号并分别写

常见错误:列类型不一致导致 UNION 失败

MySQL 对

UNION
各子查询对应列的类型有隐式转换规则,但不是万能的。比如
VARCHAR(10)
TEXT
合并可能触发警告或截断;
INT
DECIMAL(10,2)
通常可转,但
JSON
TEXT
混用会报错:
ERROR 1267 (HY000): Illegal mix of collations
或类型不兼容。

稳妥做法:

显式用
CAST()
CONVERT()
统一类型,例如:
CAST(created_at AS DATE)
避免混用
NULL
和非空字符串,可用
COALESCE(col, '')
对齐
字符集/排序规则不一致时,用
COLLATE utf8mb4_0900_as_cs
显式指定

真正容易被忽略的是:即使语句能跑通,隐式转换也可能悄悄改变数据表现——比如时间字段被转成字符串后排序失效,或者数字精度丢失。上线前务必用真实数据验证结果一致性。

相关推荐