65.9K
CodeProject 正在变化。 阅读更多。
Home

准备好学习 SQL Server:15. 学习使用 Union、Intersect 和 Except 子句

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (2投票s)

2014 年 12 月 22 日

MIT

3分钟阅读

viewsIcon

17373

学习使用 Union、Intersect 和 Except 子句

概述

这些运算符可以用于任何查询;但是,必须满足几个简单的条件

  1. 两个查询中的列数和顺序必须相同。
  2. 数据类型必须相同或兼容。

UNION 运算符

Union 运算符返回来自两个表中的行。如果单独使用,UNION 返回不同的行列表。使用 UNION ALL,将返回来自两个表的所有行。当您想将两个单独查询的结果排序为一个合并结果时,UNION 很有用。例如,如果您有两个表,VendorCustomer,并且您想要一个合并的名称列表,您可以使用以下方法轻松实现

SELECT ‘Vendor’, V.Name
FROM   Vendor V
UNION
SELECT ‘Customer’, C.Name
FROM   Customer C
ORDER BY Name

请注意,ORDER BY 子句适用于合并结果。

INTERSECT 运算符

使用 intersect 运算符返回两个表之间的共有行;它返回来自左侧和右侧查询的唯一行。当您想查找两个查询之间的共有结果时,此查询很有用。继续使用 VendorCustomer,假设您想找到也是 customervendor。您可以使用以下方法轻松实现

SELECT V.Name
FROM   Vendor V
INTERSECT
SELECT C.Name
FROM   Customer C
ORDER BY Name

您还可以使用 INNER JOIN 来回答相同的问题

SELECT Distinct V.Name
FROM   Vendor V
INNER JOIN Customer C
ON V.Name = C.Name
ORDER BY V.Name

返回相同的结果。

您会发现通常有多种方法可以解决 SQL 中的问题。

EXCEPT 运算符

使用 EXCEPT 运算符仅返回在左侧查询中找到的行。它返回来自左侧查询的、不在右侧查询结果中的唯一行。当您希望找到属于一个集合但不属于另一个集合的行时,此查询很有用。例如,要创建所有不是客户的供应商的列表,您可以编写

SELECT V.Name
FROM   Vendor V
EXCEPT
SELECT C.Name
FROM   Customer C
ORDER BY Name

INTERSECTION 一样,EXCEPT 也有一个等效的 SQL 语句。在这种情况下,我们可以使用 OUTER JOIN 来构造其等效项

SELECT Distinct V.Name
FROM   Vendor V
LEFT OUTER JOIN Customer C
ON V.Name = C.Name
WHERE C.Name is NULL
ORDER BY V.Name

棘手的事情

您可以使用这些运算符构建复杂的查询。事实上,没有什么能阻止您将一个或多个这些运算符组合成一个超级查询。完成此操作时,请务必使用括号“()”来控制首先评估哪个运算符。

您或其他 SQL 阅读者可能不清楚的是...

SELECT A FROM TA
INTERSECT
SELECT B FROM TB
EXCEPT
SELECT C FROM TB
UNION
SELECT D FROM TD

...评估为

((SELECT A FROM TA
INTERSECT
SELECT B FROM TB)
EXCEPT
SELECT C FROM TC)
UNION
SELECT D FROM TD

当没有括号时,评估顺序为

  1. INTERSECT
  2. EXCEPTUNION 从左到右进行评估

你能记住这个吗?

我的建议是只使用括号并使其清晰。棘手是酷,但当你误读自己的代码时,你会在路上被烧毁——相信我...

在这三个查询中,UNION 运算符是不可替代的。除了使用 UNION 之外,没有其他方法可以将两个查询的结果合并为一个结果。

另一方面,正如您之前看到的,EXCEPTINTERSECT 的结果都可以分别使用 OUTERINNER JOIN 来重现。事实上,您会发现查询的 JOIN 版本比 EXCEPTINTERSECT 的运行效率更高,并且更通用,因为您可以包含来自左表但不在右表中的字段。

例如:

SELECT V.Name, V.Address
FROM   Vendor V
EXCEPT
SELECT C.Name
FROM   Customer C
ORDER BY Name

无效,因为两个查询中的列数不匹配,而...

SELECT Distinct V.Name, V.Address
FROM   Vendor V
LEFT OUTER JOIN Customer C
ON V.Name = C.Name
WHERE C.Name is NULL
ORDER BY V.Name

...是有效的。

© . All rights reserved.