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





4.00/5 (2投票s)
学习使用 Union、Intersect 和 Except 子句
概述
这些运算符可以用于任何查询;但是,必须满足几个简单的条件
- 两个查询中的列数和顺序必须相同。
- 数据类型必须相同或兼容。
UNION 运算符
Union
运算符返回来自两个表中的行。如果单独使用,UNION
返回不同的行列表。使用 UNION ALL
,将返回来自两个表的所有行。当您想将两个单独查询的结果排序为一个合并结果时,UNION
很有用。例如,如果您有两个表,Vendor
和 Customer
,并且您想要一个合并的名称列表,您可以使用以下方法轻松实现
SELECT ‘Vendor’, V.Name
FROM Vendor V
UNION
SELECT ‘Customer’, C.Name
FROM Customer C
ORDER BY Name
请注意,ORDER BY
子句适用于合并结果。
INTERSECT 运算符
使用 intersect 运算符返回两个表之间的共有行;它返回来自左侧和右侧查询的唯一行。当您想查找两个查询之间的共有结果时,此查询很有用。继续使用 Vendor
和 Customer
,假设您想找到也是 customer
的 vendor
。您可以使用以下方法轻松实现
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
当没有括号时,评估顺序为
INTERSECT
EXCEPT
和UNION
从左到右进行评估
你能记住这个吗?
我的建议是只使用括号并使其清晰。棘手是酷,但当你误读自己的代码时,你会在路上被烧毁——相信我...
在这三个查询中,UNION
运算符是不可替代的。除了使用 UNION
之外,没有其他方法可以将两个查询的结果合并为一个结果。
另一方面,正如您之前看到的,EXCEPT
和 INTERSECT
的结果都可以分别使用 OUTER
和 INNER JOIN
来重现。事实上,您会发现查询的 JOIN
版本比 EXCEPT
和 INTERSECT
的运行效率更高,并且更通用,因为您可以包含来自左表但不在右表中的字段。
例如:
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
...是有效的。