MySQL 中用 UNION 可以把多个 SELECT 查询的结果纵向合并成一张结果表,要求各查询的列数、对应列的数据类型和顺序必须一致。
UNION 和 UNION ALL 的区别
UNION 会自动去重并排序(隐式 DISTINCT + ORDER BY),而 UNION ALL 直接拼接所有行,不判重、不排序,性能更高。
需要严格去重时用 UNION 确定无重复或允许重复时,优先用 UNION ALL 如果想控制排序,必须在最后加 ORDER BY(不能在单个 SELECT 后加)基本语法与列对齐规则
每个 SELECT 子句必须有相同数量的列,且对应位置的列类型最好兼容(如数字对数字、字符串对字符串),否则 MySQL 会尝试隐式转换,可能引发警告或截断。
列名以第一个 SELECT 的字段名为准 可给整个 UNION 结果起别名,但不能给中间每个 SELECT 单独起别名 WHERE、GROUP BY、LIMIT 等子句只能作用于单个 SELECT,不能跨查询使用实际应用常见场景
适合用于分表查询汇总、多条件分类统计、不同状态数据合并等。
查“今日订单”和“昨日订单”,合并展示:SELECT * FROM orders WHERE date = CURDATE() UNION ALL SELECT * FROM orders WHERE date = CURDATE() - INTERVAL 1 DAY从 user_vip 和 user_normal 表中统一查用户昵称和等级,再按等级排序:
(SELECT nickname, 'VIP' AS level FROM user_vip) UNION ALL (SELECT nickname, 'Normal' AS level FROM user_normal) ORDER BY level注意:如果某列在其中一个表里不存在,可用 NULL 或常量占位,比如
SELECT id, name, age FROM t1 UNION ALL SELECT id, title AS name, NULL AS age FROM t2
注意事项和易错点
UNION 是操作结果集,不是连接表,别和 JOIN 混淆。它不支持直接关联条件,也不能在子查询外嵌套另一个 UNION(除非用括号明确包裹)。
ORDER BY 必须放在整个语句末尾,且只生效一次 LIMIT 只能加在整个 UNION 之后,若需限制每个子查询,得用派生表或 CTE 如果某个 SELECT 用了 LIMIT,必须用括号包住,否则语法报错 字符集不一致可能导致 UNION 失败,建议统一字段 collation