前言
在MySQL数据库的世界里,数据查询是一项核心操作。而UNION
操作符作为数据查询中的一个强大工具,能够帮助开发者高效地处理多个结果集的合并。
1. 什么是UNION操作符
在MySQL中,UNION
并不是一个函数,而是一个用于合并两个或多个SELECT
语句结果集的操作符。它就像是一个数据整合器,将不同SELECT
语句获取到的数据合并在一起,形成一个统一的结果集,方便用户进行数据分析和处理。
2. 基本语法
UNION
操作符的基本语法结构如下:
SELECT column1, column2,...
FROM table1
UNION
SELECT column3, column4,...
FROM table2;
在这个语法中,首先是第一个SELECT
查询,它从table1
表中选择指定的列column1, column2,...
。然后通过UNION
操作符,将其与第二个SELECT
查询的结果进行合并,第二个查询从table2
表中选择列column3, column4,...
。
3. 字段要求
3.1 列数必须相同
使用UNION
时,一个严格的要求是所有参与UNION
操作的SELECT
语句中的列数必须相同。这是因为UNION
操作本质上是按行将多个结果集纵向拼接,只有列数一致,才能确保每一行的数据在合并后有正确的列对应关系。例如:
-- 正确示例,列数相同
SELECT id, name
FROM users
UNION
SELECT product_id, product_name
FROM products;
-- 错误示例,列数不同
SELECT id, name
FROM users
UNION
SELECT product_id, product_name, price
FROM products;
上述错误示例中,第一个SELECT
语句选择了2列,而第二个SELECT
语句选择了3列 ,MySQL会抛出语法错误。
3.2 对应列数据类型兼容
除了列数相同,对应列的数据类型也必须兼容。所谓兼容,指的是数据类型要么完全相同,要么可以在MySQL中进行隐式类型转换。例如,如果第一个SELECT
语句中的某列是INT
类型,那么第二个SELECT
语句中对应位置的列也应该是INT
类型,或者是可以隐式转换为INT
类型的数据类型,如SMALLINT
、TINYINT
等数值类型。
-- 正确示例,数据类型兼容
SELECT id, name
FROM users
UNION
SELECT CAST(order_id AS SIGNED), customer_name
FROM orders;
-- 错误示例,数据类型不兼容
SELECT id, name
FROM users
UNION
SELECT order_date, customer_name
FROM orders;
上述错误示例中,id
是数值类型,而order_date
是日期类型,两者不兼容,无法进行UNION
操作。
3.3 列名以首个SELECT为准
值得注意的是,在UNION
操作中,结果集的列名通常会以第一个SELECT
语句中的列名为准。即使后续SELECT
语句中列的别名不同,最终结果集也会采用第一个SELECT
的列名。例如:
SELECT id AS user_id, name AS user_name
FROM users
UNION
SELECT product_id, product_name
FROM products;
在这个例子中,最终结果集的列名是user_id
和user_name
,而不是product_id
和product_name
。
4. 特点
4.1 结果集去重
默认情况下,UNION
操作会去除合并结果集中的重复行。这意味着,如果两个SELECT
语句返回的结果中有相同的行,最终只会在结果集中出现一次。例如:
SELECT 'apple' AS fruit
UNION
SELECT 'apple' AS fruit;
上述查询结果只会包含一行'apple'
,重复的行被去除了。
4.2 结果集排序
UNION
操作后的结果集可以使用ORDER BY
子句进行排序。如果没有指定ORDER BY
,则结果集的顺序是不确定的。需要注意的是,ORDER BY
子句通常放在最后一个SELECT
语句之后,它会对整个UNION
操作后的结果集进行排序。例如:
SELECT name, salary
FROM employees
UNION
SELECT name, salary
FROM contractors
ORDER BY salary DESC;
上述查询会先合并employees
表和contractors
表中的数据,然后按照salary
列降序排列整个结果集。
4.3 性能考虑
UNION
操作在合并结果集时可能会有一定的性能开销,特别是在处理大量数据时。这是因为UNION
默认会去除重复的行,这个去重过程需要额外的计算资源。如果使用UNION ALL
,由于不需要去除重复行,性能可能会更好一些。因此,在实际应用中,如果能够确定合并后的结果集中不会有重复行,或者重复行对业务没有影响,那么优先选择UNION ALL
可以提高查询效率。
5. 示例
假设有两个表employees
和contractors
,它们都包含name
和salary
列,以下是使用UNION
和UNION ALL
的示例:
5.1 使用UNION
SELECT name, salary
FROM employees
UNION
SELECT name, salary
FROM contractors;
上述查询会合并employees
表和contractors
表中的name
和salary
列,并去除重复的行。如果有员工和承包商的姓名和薪资完全相同,那么在最终结果集中只会出现一次。
5.2 使用UNION ALL
SELECT name, salary
FROM employees
UNION ALL
SELECT name, salary
FROM contractors;
这个查询会合并两个表中的数据,包括重复的行。即使有员工和承包商的姓名和薪资完全相同,它们也会在结果集中分别出现。
6. 与其他操作符对比
6.1 与JOIN对比
JOIN
用于根据两个或多个表之间的关联条件将它们的行组合在一起,通常用于获取来自多个表的相关数据。例如,通过JOIN
可以将employees
表和departments
表关联起来,获取每个员工所在的部门信息。而UNION
用于合并来自不同查询的结果集,这些查询可能基于不同的表或相同表的不同条件。简单来说,JOIN
是横向连接数据,UNION
是纵向合并数据。
6.2 与INTERSECT和EXCEPT对比
在一些数据库中,还存在INTERSECT
和EXCEPT
操作符。INTERSECT
用于返回两个查询结果集的交集,即同时存在于两个结果集中的行;EXCEPT
用于返回在第一个查询结果集中但不在第二个查询结果集中的行。MySQL本身没有直接的INTERSECT
和EXCEPT
操作符,但可以通过其他方式实现类似的功能。例如,可以使用IN
子查询或JOIN
操作来模拟INTERSECT
和EXCEPT
的效果。