目录
[4.1 两张表字段相同,字段顺序也相同](#4.1 两张表字段相同,字段顺序也相同)
[4.2 两张表字段相同。但字段顺序不同](#4.2 两张表字段相同。但字段顺序不同)
[4.3 两张表存在相同字段,但一张表字段多,一张表字段少](#4.3 两张表存在相同字段,但一张表字段多,一张表字段少)
一、基本概念
|-----------|-----------------------|------|-----------|
| 操作符 | 功能描述 | 去重处理 | 性能对比 |
| UNION | 合并多个查询结果,自动去除重复行 | 是 | 较低(需排序去重) |
| UNION ALL | 合并多个查询结果,保留所有行(包括重复行) | 否 | 较高 |
二、核心区别
|--------|------------|------------|
| 对比维度 | UNION | UNION ALL |
| 重复数据处理 | 自动去重 | 保留所有重复行 |
| 执行效率 | 较慢(需排序和去重) | 较快(直接合并结果) |
| 资源消耗 | 高(涉及临时表排序) | 低 |
| 排序行为 | 结果集默认无明确顺序 | 结果集默认无明确顺序 |
| 适用场景 | 需唯一结果的合并 | 需保留所有记录的合并 |
上面两张表不需要要小伙伴们全部记下来,当然啦,能记住最好。
主要记住一句话**"UNION 会去重,效率低;UNION ALL 不去重,效率高;且二者都不会自动排序"。**
三、语法使用规则
UNION 和 UNION ALL 语法规则是一样的,如下实例SQL
sql
-- UNION 语法
SELECT column1, column2 FROM table1
UNION
SELECT column1, column2 FROM table2;
-- 这里使用了 column1, column2将字段一一列出来,如果 table1和table2字段的顺序一致,可以直接写为 select * ,下方 UNION ALL 同理
select * from table1
UNION
SELECT * FROM table2;
-- UNION ALL 语法
SELECT column1, column2 FROM table1
UNION ALL
SELECT column1, column2 FROM table2;
或
select * from table1
UNION ALL
SELECT * FROM table2;
但需要注意以下三点:
(1)列数一致:所有 SELECT 语句的列数必须相同;
(2)数据类型兼容:对应列的数据类型需兼容(如 VARCHAR 与 TEXT 兼容);
(3)列名规则:最终结果集的列名以第一个 SELECT 的列名为准;
四、代码实演示
4.1 两张表字段相同,字段顺序也相同
user1 表数据如下图

user2 表数据如下图

此时 user1 和 user2 两个表字段完全相同,但数据略有不同,两张表都有相同的 "张三"、"李四"、"王五";
(1)使用 UNION,结果如下图。
因为两张表的"张三"、"李四"、"王五" 完全相同,所以 UNION 帮我们自动去重了,查询合并后的结果就是7条数据;

(2)使用 UNION ALL,结果如下图。
UNION ALL 不会自动去重,而是将两张表的全部数据合并,一共十条数据;

4.2 两张表字段相同。但字段顺序不同
user1 表数据如下图

user4 表数据如下图

此时由于两张表字段顺序,我们不能直接使用 select * ,虽然username,password 都是 VARCHAR 类型可以兼容,但是查询到的数据会报错
如下图,不管是 UNION,还是UNION ALL,最终的表字段顺序会以第一张表 user1 的字段顺序为准,这就会产生一个问题,我 user4 表中,passwor 和 username 顺序是反着的,因为没有转化,就会导致查询到的结果中,user4 表的查询结果,用户的密码 password 被当作 username,用户的 username 被当作 password;造成数据错误。

这种情况下,我们就不能直接使用 SELECT *,而是需要将字段一一对应。
如下图中代码所示,我们需要将字段一一列出,并让两张表的字段顺序也与之对应,我这里使用 AS 关键字取别名,实际开发过程中也较为常见,有时候 table1 用户名字段可能为 username,table2 表中用户名字段可能为 name,我们就为查询结果的虚拟表字段取别名,方便我们理解。

4.3 两张表存在相同字段,但一张表字段多,一张表字段少
这也是一种较为常见的情况,比如我 table1 表中有 A,B,C三个字段;table2 有A,B,C,D四个字段,我希望对这两张表UNION合并取出查询结果。
如下为 user1 表数据

如下为 user3 表数据,

与之对比,user3 少了一个 age 年龄字段。
此时,我们如果使用 SELECT * 去 查询,会报错。如下图,报错称"两张表有不同数量的列"。

此时我们就需要"补列字段" ,因为 user3 没有 age 字段,我们要在查询结果中进行填充;
如下,我们使用 "NULL AS age"对查询结果中 user3 的age字段进行填充,使其全部为 NULL,这样就可以与 user1 进行UNION 或 UNION ALL啦!

当然,我们也可以不使用 NULL 进行填充,使用任何数据都可以。
例如空字符串'',这样一来查询结果就全部都是空字符串了。

也可以使用具体数据,比如 age 为年龄,我们就让没有这个字段的,全部默认填充为 18。
如下图

OK小伙伴们,以上三种情况基本上涵盖了多表进行 UNION,UNION ALL 的全部情况啦!不难理解,有需要自动动手尝试的小伙伴,我就把建表SQL放在文章最下面了,自取即可。
sql
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user1
-- ----------------------------
DROP TABLE IF EXISTS `user1`;
CREATE TABLE `user1` (
`uid` int NOT NULL,
`username` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL,
`age` int NULL DEFAULT NULL,
PRIMARY KEY (`uid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_unicode_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user1
-- ----------------------------
INSERT INTO `user1` VALUES (1, '张三', '123', 17);
INSERT INTO `user1` VALUES (2, '李四', '1234', 18);
INSERT INTO `user1` VALUES (3, '王五', '12345', 18);
INSERT INTO `user1` VALUES (4, '赵六', '12346', 19);
INSERT INTO `user1` VALUES (5, '123', '12345', 20);
DROP TABLE IF EXISTS `user2`;
CREATE TABLE `user2` (
`uid` int NOT NULL,
`username` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL,
`age` int NULL DEFAULT NULL,
PRIMARY KEY (`uid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_unicode_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user2
-- ----------------------------
INSERT INTO `user2` VALUES (1, '张三', '123', 17);
INSERT INTO `user2` VALUES (2, '李四', '1234', 18);
INSERT INTO `user2` VALUES (3, '王五', '12345', 18);
INSERT INTO `user2` VALUES (4, '赵六', '12345', 19);
INSERT INTO `user2` VALUES (5, '123456', '123454536', 21);
DROP TABLE IF EXISTS `user3`;
CREATE TABLE `user3` (
`uid` int NOT NULL,
`username` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL,
PRIMARY KEY (`uid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_unicode_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user3
-- ----------------------------
INSERT INTO `user3` VALUES (1, '张三', '123');
INSERT INTO `user3` VALUES (2, '李四', '1234');
INSERT INTO `user3` VALUES (4, '赵六', '12346');
INSERT INTO `user3` VALUES (5, '123456', '123454536');
DROP TABLE IF EXISTS `user4`;
CREATE TABLE `user4` (
`uid` int NOT NULL,
`password` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL,
`username` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL,
`age` int NULL DEFAULT NULL,
PRIMARY KEY (`uid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_unicode_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user4
-- ----------------------------
INSERT INTO `user4` VALUES (1, 'afd'', 'ewfew', 11);
INSERT INTO `user4` VALUES (2, 'defg', 'ergegwr', 19);
INSERT INTO `user4` VALUES (3, 'fdgg', 'fwe', 55);
INSERT INTO `user4` VALUES (4, '而我4', '3544', 18);
INSERT INTO `user4` VALUES (5, '12345', '123', 20);
SET FOREIGN_KEY_CHECKS = 1;