如何利用 SQL UNION 操作符将多条 SELECT 语句组合成一个结果集

本文介绍如何利用 SQL UNION 操作符将多条 SELECT 语句组合成一个结果集。使用 UNION 可极大地简化复杂的 WHERE 子句,简化从多个表中检索数据的工作。

一、组合查询

多数 SQL 查询只包含从一个或多个表中返回数据的单条 SELECT 语句。但是,SQL 也允许执行多个查询(多条 SELECT 语句),并将结果作为一个查询结果集返回。

这些组合查询通常称为并(union)或复合查询(compound query)。

主要有两种情况需要使用组合查询:

  • 在一个查询中从不同的表返回结构数据;
  • 对一个表执行多个查询,按一个查询返回数据。

二、创建组合查询

可用 UNION 操作符来组合数条 SQL 查询。利用 UNION,可给出多条 SELECT 语句,将它们的结果组合成一个结果集。

2.1 使用 UNION

使用 UNION 很简单,所要做的只是给出每条 SELECT 语句,在各条语句之间放上关键字 UNION

举个例子,假如需要 IllinoisIndianaMichigan 等美国几个州的所有顾客的报表,还想包括不管位于哪个州的所有的 Fun4All

当然可以利用 WHERE 子句来完成此工作,不过这次我们使用 UNION

如上所述,创建 UNION 涉及编写多条 SELECT 语句。首先来看单条语句:

1
2
3
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI');

输出:

1
2
3
4
5
cust_name       cust_contact      cust_email
-----------     -------------     ------------
Village Toys    John Smith        [email protected]
Fun4All         Jim Jones         [email protected]
The Toy Store   Kim Howard        NULL

输入:

1
2
3
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All';

输出:

1
2
3
4
cust_name       cust_contact         cust_email
-----------     -------------        ------------
Fun4All         Jim Jones            [email protected]
Fun4All         Denise L. Stephens   [email protected]

第一条 SELECTIllinoisIndianaMichigan 等州的缩写传递给 IN 子句,检索出这些州的所有行。

第二条 SELECT 利用简单的相等测试找出所有 Fun4All。你会发现有一条记录出现在两次结果里,因为它满足两次的条件。

组合这两条语句,可以如下进行:

1
2
3
4
5
6
7
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All';

输出:

1
2
3
4
5
6
cust_name       cust_contact        cust_email
-----------     -----------         ----------------
Fun4All         Denise L. Stephens  [email protected]
Fun4All         Jim Jones           [email protected]
Village Toys    John Smith          [email protected]
The Toy Store   Kim Howard          NULL

这条语句由前面的两条 SELECT 语句组成,之间用 UNION 关键字分隔。UNION 指示 DBMS 执行这两条 SELECT 语句,并把输出组合成一个查询结果集。

为了便于参考,这里给出使用多条 WHERE 子句而不是 UNION 的相同查询:

1
2
3
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI') OR cust_name='Fun4All';

在这个简单的例子中,使用 UNION 可能比使用 WHERE 子句更为复杂。但对于较复杂的过滤条件,或者从多个表(而不是一个表)中检索数据的情形,使用 UNION 可能会使处理更简单。

2.2 UNION 规则

可以看到,UNION 非常容易使用,但在进行组合时需要注意几条规则。

  • UNION 必须由两条或两条以上的 SELECT 语句组成,语句之间用关键字 UNION 分隔(因此,如果组合四条 SELECT 语句,将要使用三个 UNION 关键字)。
  • UNION 中的每个查询必须包含相同的列、表达式或聚集函数(不过,各个列不需要以相同的次序列出)。
  • 列数据类型必须兼容:类型不必完全相同,但必须是 DBMS 可以隐含转换的类型(例如,不同的数值类型或不同的日期类型)。

如果遵守了这些基本规则或限制,则可以将 UNION 用于任何数据检索操作。

2.3 包含或取消重复的行

回到 2.1 节,我们看看所用的 SELECT 语句。

注意到在分别执行语句时,第一条 SELECT 语句返回 3 行,第二条 SELECT 语句返回 2 行。而在用 UNION 组合两条 SELECT 语句后,只返回 4 行而不是 5 行。

UNION 从查询结果集中自动去除了重复的行;换句话说,它的行为与一条 SELECT 语句中使用多个 WHERE 子句条件一样。

因为 Indiana 州有一个 Fun4All 单位,所以两条 SELECT 语句都返回该行。使用 UNION 时,重复的行会被自动取消。

这是 UNION 的默认行为,如果愿意也可以改变它。事实上,如果想返回所有的匹配行,可使用 UNION ALL 而不是 UNION

请看下面的例子:

1
2
3
4
5
6
7
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
UNION ALL
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All';

输出:

1
2
3
4
5
6
7
cust_name       cust_contact         cust_email
-----------     -------------        ------------
Village Toys    John Smith           [email protected]
Fun4All         Jim Jones            [email protected]
The Toy Store   Kim Howard           NULL
Fun4All         Jim Jones            [email protected]
Fun4All         Denise L. Stephens   [email protected]

使用 UNION ALL,DBMS 不取消重复的行。因此,这里返回 5 行,其中有一行出现两次。

2.4 对组合查询结果排序

SELECT 语句的输出用 ORDER BY 子句排序。

在用 UNION 组合查询时,只能使用一条 ORDER BY 子句,它必须位于最后一条 SELECT 语句之后。

对于结果集,不存在用一种方式排序一部分,而又用另一种方式排序另一部分的情况,因此不允许使用多条 ORDER BY 子句。

下面的例子对前面 UNION 返回的结果进行排序:

1
2
3
4
5
6
7
8
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All'
ORDER BY cust_name, cust_contact;

输出:

1
2
3
4
5
6
cust_name       cust_contact         cust_email
-----------     -------------        -------------
Fun4All         Denise L. Stephens   [email protected]
Fun4All         Jim Jones            [email protected]
The Toy Store   Kim Howard           NULL
Village Toys    John Smith           [email protected]

这条 UNION 在最后一条 SELECT 语句后使用了 ORDER BY 子句。

虽然 ORDER BY 子句似乎只是最后一条 SELECT 语句的组成部分,但实际上 DBMS 将用它来排序所有 SELECT 语句返回的所有结果。

三、小结

本文介绍了如何用 UNION 操作符来组合 SELECT 语句。利用 UNION,可以把多条查询的结果作为一条组合查询返回,不管结果中有无重复。

使用 UNION 可极大地简化复杂的 WHERE 子句,简化从多个表中检索数据的工作。

(完)