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
显式指定

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

相关推荐