UNION,UNION ALL 的详细用法

发布于:2025-03-18 ⋅ 阅读:(17) ⋅ 点赞:(0)

目录

一、基本概念

二、核心区别

三、语法使用规则

四、代码实演示

4.1 两张表字段相同,字段顺序也相同

4.2 两张表字段相同。但字段顺序不同

4.3 两张表存在相同字段,但一张表字段多,一张表字段少


一、基本概念

操作符 功能描述 去重处理 性能对比
UNION 合并多个查询结果,自动去除重复行 较低(需排序去重)
UNION ALL 合并多个查询结果,保留所有行(包括重复行) 较高

二、核心区别

对比维度 UNION UNION ALL
重复数据处理 自动去重 保留所有重复行
执行效率 较慢(需排序和去重) 较快(直接合并结果)
资源消耗 高(涉及临时表排序)
排序行为 结果集默认无明确顺序 结果集默认无明确顺序
适用场景 需唯一结果的合并 需保留所有记录的合并

上面两张表不需要要小伙伴们全部记下来,当然啦,能记住最好。

主要记住一句话"UNION 会去重,效率低;UNION ALL 不去重,效率高;且二者都不会自动排序"。

三、语法使用规则

UNION 和 UNION ALL 语法规则是一样的,如下实例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放在文章最下面了,自取即可。

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;