UNION (Transact-SQL)
将两个或更多查询的结果合并为单个结果集,该结果集包含联合查询中的所有查询的全部行。UNION 运算不同于使用联接合并两个表中的列的运算。
下面列出了使用 UNION 合并两个查询结果集的基本规则:
所有查询中的列数和列的顺序必须相同。
数据类型必须兼容。
语法
{ <query_specification> | ( <query_expression> ) }
UNION [ ALL ]
<query_specification | ( <query_expression> )
[ UNION [ ALL ] <query_specification> | ( <query_expression> )
[ ...n ] ]
参数
<query_specification> | ( <query_expression> )
查询规范或查询表达式,用以返回要与另一个查询规范或查询表达式所返回的数据合并的数据。作为 UNION 运算的一部分的列定义可以不相同,但它们必须通过隐式转换实现兼容。如果数据类型不同,则根据数据类型优先级规则确定所产生的数据类型。如果类型相同,但精度、小数位数或长度不同,则根据用于合并表达式的相同规则来确定结果。有关详细信息,请参阅 精度、小数位数和长度 (Transact-SQL)。xml 数据类型的列必须等价。所有的列必须类型化为 XML 架构或是非类型化的。如果要类型化,这些列必须类型化为相同的 XML 架构集合。
UNION
指定合并多个结果集并将其作为单个结果集返回。ALL
将全部行并入结果中。其中包括重复行。如果未指定该参数,则删除重复行。
示例
A. 使用简单 UNION
在下面的示例中,结果集同时包含 ProductModel 和 Gloves 表中的 ProductModelID 与 Name 列中的内容。
USE AdventureWorks;
GO
IF OBJECT_ID ('dbo.Gloves', 'U') IS NOT NULL
DROP TABLE dbo.Gloves;
GO
-- Create Gloves table.
SELECT ProductModelID, Name
INTO dbo.Gloves
FROM Production.ProductModel
WHERE ProductModelID IN (3, 4);
GO
-- Here is the simple union.
USE AdventureWorks;
GO
SELECT ProductModelID, Name
FROM Production.ProductModel
WHERE ProductModelID NOT IN (3, 4)
UNION
SELECT ProductModelID, Name
FROM dbo.Gloves
ORDER BY Name;
GO
B. 将 SELECT INTO 与 UNION 一起使用
在下面的示例中,第二个 SELECT 语句中的 INTO 子句指定名为 ProductResults 的表存放 ProductModel 和 Gloves 表中的指定列的并集(最终结果集)。注意,Gloves 表是由第一个 SELECT 语句创建的。
USE AdventureWorks;
GO
IF OBJECT_ID ('dbo.ProductResults', 'U') IS NOT NULL
DROP TABLE dbo.ProductResults;
GO
IF OBJECT_ID ('dbo.Gloves', 'U') IS NOT NULL
DROP TABLE dbo.Gloves;
GO
-- Create Gloves table.
SELECT ProductModelID, Name
INTO dbo.Gloves
FROM Production.ProductModel
WHERE ProductModelID IN (3, 4);
GO
USE AdventureWorks;
GO
SELECT ProductModelID, Name
INTO dbo.ProductResults
FROM Production.ProductModel
WHERE ProductModelID NOT IN (3, 4)
UNION
SELECT ProductModelID, Name
FROM dbo.Gloves;
GO
SELECT *
FROM dbo.ProductResults;
C. 将 ORDER BY 与两个 SELECT 语句的 UNION 一起使用
在 UNION 子句中使用的某些参数的顺序非常重要。下面的示例通过两个 SELECT 语句说明 UNION 的错误用法和正确用法(在这两个语句的输出中将重命名一个列)。
USE AdventureWorks;
GO
IF OBJECT_ID ('dbo.Gloves', 'U') IS NOT NULL
DROP TABLE dbo.Gloves;
GO
-- Create Gloves table.
SELECT ProductModelID, Name
INTO dbo.Gloves
FROM Production.ProductModel
WHERE ProductModelID IN (3, 4);
GO
/* INCORRECT */
USE AdventureWorks;
GO
SELECT ProductModelID, Name
FROM Production.ProductModel
WHERE ProductModelID NOT IN (3, 4)
ORDER BY Name
UNION
SELECT ProductModelID, Name
FROM dbo.Gloves;
GO
/* CORRECT */
USE AdventureWorks;
GO
SELECT ProductModelID, Name
FROM Production.ProductModel
WHERE ProductModelID NOT IN (3, 4)
UNION
SELECT ProductModelID, Name
FROM dbo.Gloves
ORDER BY Name;
GO
D. 使用三个 SELECT 语句的 UNION 来说明 ALL 和括号的作用
下面的示例使用 UNION 来组合具有相同 5 行数据的三个表的结果。第一个示例使用 UNION ALL 显示重复记录,返回所有的 15 行。第二个示例使用不带 ALL 的 UNION,删除三个 SELECT 语句的组合结果中的重复行,返回 5 行。
第三个示例将 ALL 用于第一个 UNION,并用括号将第二个没有使用 ALL 的 UNION 括起来。第二个 UNION 因位于括号内而首先得到处理,并且因为没有使用 ALL 选项,所以重复行被删除而返回 5 行。通过使用 UNION ALL 关键字将这 5 行与第一个 SELECT 的结果组合在一起。这不会删除两个 5 行结果集之间的重复行。最终结果有 10 行。
USE AdventureWorks;
GO
IF OBJECT_ID ('dbo.EmployeeOne', 'U') IS NOT NULL
DROP TABLE EmployeeOne;
GO
IF OBJECT_ID ('dbo.EmployeeTwo', 'U') IS NOT NULL
DROP TABLE EmployeeTwo;
GO
IF OBJECT_ID ('dbo.EmployeeThree', 'U') IS NOT NULL
DROP TABLE EmployeeThree;
GO
SELECT c.LastName, c.FirstName, e.Title
INTO dbo.EmployeeOne
FROM Person.Contact AS c JOIN HumanResources.Employee AS e
ON e.ContactID = c.ContactID
WHERE ManagerID = 66;
GO
SELECT c.LastName, c.FirstName, e.Title
INTO dbo.EmployeeTwo
FROM Person.Contact AS c JOIN HumanResources.Employee AS e
ON e.ContactID = c.ContactID
WHERE ManagerID = 66;
GO
SELECT c.LastName, c.FirstName, e.Title
INTO dbo.EmployeeThree
FROM Person.Contact AS c JOIN HumanResources.Employee AS e
ON e.ContactID = c.ContactID
WHERE ManagerID = 66;
GO
-- Union ALL
SELECT LastName, FirstName
FROM dbo.EmployeeOne
UNION ALL
SELECT LastName, FirstName
FROM dbo.EmployeeTwo
UNION ALL
SELECT LastName, FirstName
FROM dbo.EmployeeThree;
GO
SELECT LastName, FirstName
FROM dbo.EmployeeOne
UNION
SELECT LastName, FirstName
FROM dbo.EmployeeTwo
UNION
SELECT LastName, FirstName
FROM dbo.EmployeeThree;
GO
SELECT LastName, FirstName
FROM dbo.EmployeeOne
UNION ALL
(
SELECT LastName, FirstName
FROM dbo.EmployeeTwo
UNION
SELECT LastName, FirstName
FROM dbo.EmployeeThree
);
GO