I'm going to focus on EXCEPT
just because I'm more familiar with it. Also, as a disclaimer, my examples will be in Sqlite, since I'm on a Linux box. However, both Sqlite and SQL Server should support the functionality.
Both INTERSECT
and EXCEPT
are set operators, stemming from the underlying ideas in relational algebra. They operate on distinct values, being set operators.
Your example is simplistic. I'll give a counterexample, using a Sqlite version of the Northwind sample database.
Let's say that you want to get the CustomerIDs of all customers who made an order with EmployeeID of 5, but NOT those who also made an order with EmployeeID of 6. This is simple and natural with an EXCEPT
.
SELECT CustomerID FROM orders
WHERE EmployeeID = 5
EXCEPT
SELECT CustomerID FROM orders
WHERE EmployeeID = 6
This returns 14 rows on my version of Northwind.
Suppose you decide to rewrite this using JOIN
s. Maybe something like this?
SELECT o1.CustomerID
FROM orders o1 INNER JOIN orders o2 ON o1.CustomerID = o2.CustomerID
WHERE o1.EmployeeID = 5 AND o2.EmployeeID != 6
Whoops, 525 rows. Maybe add a DISTINCT
?
SELECT DISTINCT o1.CustomerID
FROM orders o1 INNER JOIN orders o2 ON o1.CustomerID = o2.CustomerID
WHERE o1.EmployeeID = 5 AND o2.EmployeeID != 6
Now it's 28 rows, still much more than what we were getting with EXCEPT
. The reason is that this isn't removing CustomerIDs that have made an order with 6. Rather, it returns all CustomerIDs that have an order with 5 and some EmployeeID other than 6, whether or not they also have an order with EmployeeID 6.
In short, EXCEPT
and INTERSECT
are set operators that compare two queries, returning unique tuples, and certainly have their use.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…