SQL中的集合操作(set operations)是一类允许将多个查询的结果合并为单个结果集的操作。[1]SQL集合运算符包括 UNION(并集)、INTERSECT(交集)和 EXCEPT(差集),它们在数学集合论上对应于并集、交集、差集概念。
UNION运算符
编辑在SQL中,UNION子句将两个SQL查询的结果合并为一个包含所有匹配行的单表。为了进行合并,两个查询必须产生相同数量的列,且对应列的数据类型必须兼容。除非使用UNION ALL,否则所有重复记录都会被自动移除。
在数据表未完全规范化(Normalized)的数据仓库应用中,UNION非常有用。[2]一个简单的例子是:数据库中有sales2005和sales2006两张表,它们结构完全相同,但出于性能考虑被拆分。使用UNION查询可以将这两张表的结果合并。
UNION ALL不保证行的顺序。第二个查询的行可能出现在第一个查询的行之前、之后或与之混杂。如果需要特定顺序,必须使用ORDER BY。
UNION ALL通常比普通的 UNION 快得多。
例子
编辑给定2张表:
| person | amount |
|---|---|
| Joe | 1000 |
| Alex | 2000 |
| Bob | 5000 |
| person | amount |
|---|---|
| Joe | 2000 |
| Alex | 2000 |
| Zach | 35000 |
执行下属语句:
SELECT * FROM sales2005
UNION
SELECT * FROM sales2006;
产生下述结果集,行的顺序不定因为没有ORDER BY子句:
| person | amount |
|---|---|
| Joe | 1000 |
| Alex | 2000 |
| Bob | 5000 |
| Joe | 2000 |
| Zach | 35000 |
注意Joe有两行因为这两行的列值并不完全相同。Alex只有一行因为冗余的行会被删除。
UNION ALL给出不同的结果,它并不删除冗余:
SELECT * FROM sales2005
UNION ALL
SELECT * FROM sales2006;
结果集为:
| person | amount |
|---|---|
| Joe | 1000 |
| Joe | 2000 |
| Alex | 2000 |
| Alex | 2000 |
| Bob | 5000 |
| Zach | 35000 |
full outer joins就是使用UNION的例子。
INTERSECT 运算符
编辑SQL的INTERSECT(交集)运算符接收两个查询的结果,并且只返回同时出现在这两个结果集中的行。出于去重的目的,INTERSECT 运算符将所有的NULL值视为相同(即不会区分它们)。INTERSECT运算符会从最终的结果集中移除重复的行。
INTERSECT ALL运算符不会从最终结果集中移除重复行。但是,如果某一行在第一个查询中出现了X次,在第二个查询中出现了Y次,那么它在最终结果集中将会出现 (即X和Y中的较小值)次。
例子
编辑SELECT *
FROM Orders
WHERE Quantity BETWEEN 1 AND 100
INTERSECT
SELECT *
FROM Orders
WHERE Quantity BETWEEN 50 AND 200;
EXCEPT operator
编辑EXCEPT 运算符 SQL 的 EXCEPT(差集)运算符提取第一个查询结果中的去重行,并返回那些没有出现在第二个结果集中的行。出于消除行和去除重复项的目的,EXCEPT 运算符不会区分 NULL 值(即把多个 NULL 视为相同并去重)。
EXCEPT ALL 运算符 EXCEPT ALL 运算符不会去除重复项。但是,如果某一行在第一个查询中出现了 X 次,在第二个查询中出现了 Y 次,那么它在最终结果集中将出现 max(X-Y, 0) 次。
值得注意的是,Oracle平台提供了一个MINUS运算符,它在功能上完全等同于SQL:2003标准中的EXCEPT DISTINCT(即普通的 EXCEPT)运算符。[3]
示例1
编辑The following example EXCEPT query returns all rows from the Orders table where Quantity is between 1 and 49, and those with a Quantity between 76 and 100.
(假设有)以下EXCEPT查询示例,它返回 Orders 表中数量(Quantity)在 1 到 49 之间,以及 76 到 100 之间的所有行。 换种说法:该查询返回数量在 1 到 100 之间的所有行,但扣除(排除了)那些数量在 50 到 75 之间的行。
SELECT *
FROM Orders
WHERE Quantity BETWEEN 1 AND 100
EXCEPT
SELECT *
FROM Orders
WHERE Quantity BETWEEN 50 AND 75;
示例2
编辑下例不使用EXCEPT运算符也能实现同样功能。
SELECT o1.*
FROM (
SELECT *
FROM Orders
WHERE Quantity BETWEEN 1 AND 100) o1
LEFT JOIN (
SELECT *
FROM Orders
WHERE Quantity BETWEEN 50 AND 75) o2
ON o1.id = o2.id
WHERE o2.id IS NULL
参考文献
编辑- ^ The UNION [ALL], INTERSECT, MINUS Operators. Oracle. [14 July 2016]. (原始内容存档于2025-05-30).
- ^ "a
UNION ALLviews technique for managing maintenance and performance in your large data warehouse environment ... ThisUNION ALLtechnique has saved many of my clients with issues related to time-sensitive database designs. These databases usually have an extremely volatile current timeframe, month, or day portion and the older data is rarely updated. Using different container DASD allocations, tablespaces, tables, and index definitions, the settings can be tuned for the specific performance considerations for these different volatility levels and update frequency situations." Terabyte Data Warehouse Table Design Choices - Part 2 (页面存档备份,存于互联网档案馆) (accessed on July 25, 2006) - ^ "E071-03,
EXCEPT DISTINCTtable operator: UseMINUSinstead ofEXCEPT DISTINCT" Oracle Compliance To Core SQL:2003. Docs.oracle.com. [7 July 2022]. (原始内容存档于2025-01-24).
外部链接
编辑- MSDN documentation on UNION in Transact-SQL for SQL Server (页面存档备份,存于互联网档案馆)
- Naming of select list items in set operations (页面存档备份,存于互联网档案馆)
- UNION in MySQL with Examples (页面存档备份,存于互联网档案馆)
- UNION in MySQL (页面存档备份,存于互联网档案馆)
- UNION Clause in PostgreSQL (页面存档备份,存于互联网档案馆)
- SQL UNION and UNION ALL
- Sort order within UNION statement (页面存档备份,存于互联网档案馆)
- Designing a data flow that loads a warehouse table
- Oracle 11g documentation for UNION (ALL), INTERSECT and MINUS (页面存档备份,存于互联网档案馆)
- SQL Set Operators (页面存档备份,存于互联网档案馆)