UNION,UNION ALL 的详细用法

目录

一、基本概念

二、核心区别

三、语法使用规则

四、代码实演示

[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;
相关推荐
咖啡の猫3 小时前
数据库的基本概念
数据库
小卓笔记4 小时前
keepalived应用
linux·服务器·数据库
八股文领域大手子5 小时前
Leetcode32 最长有效括号深度解析
java·数据库·redis·sql·mysql
鹏神丶明月天6 小时前
mybatis_plus的乐观锁
java·开发语言·数据库
SelectDB技术团队6 小时前
天翼云:Apache Doris + Iceberg 超大规模湖仓一体实践
大数据·数据库·iceberg·doris·数据湖·湖仓一体·天翼云
江湖有缘8 小时前
华为云之MySQL数据的导入导出实践【玩转华为云】
数据库·mysql·华为云
PersistJiao8 小时前
将数据添加到 Couchbase 的 Analytics(分析)服务
数据库·couchbase
Honmaple8 小时前
Redis 三主三从集群部署的完整方案
数据库·redis·缓存
James. 常德 student8 小时前
高频SQL 50 题(持续更新)
数据库·sql·adb