Я собираюсь сосредоточиться на EXCEPT
только потому, что я более знаком с этим. Кроме того, в качестве отказа от ответственности, мои примеры будут в Sqlite, так как я на Linux box. Однако и Sqlite, и SQL Server должны поддерживать эту функциональность.
И INTERSECT
, и EXCEPT
являются операторами множеств, вытекающими из основополагающих идей реляционной алгебры . Они работают с отличными значениями , будучи заданными операторами.
Ваш пример упрощен. Я приведу контрпример, используя версию Sqlite Northwind образца базы данных.
Допустим, вы хотите получить CustomerID всех клиентов, которые сделали заказ с EmployeeID, равным 5, но НЕ тех, кто также сделал заказ с EmployeeID, равным 6. Это просто и естественно с EXCEPT
.
SELECT CustomerID FROM orders
WHERE EmployeeID = 5
EXCEPT
SELECT CustomerID FROM orders
WHERE EmployeeID = 6
Это возвращает 14 строк в моей версии Northwind.
Предположим, вы решили переписать это, используя JOIN
s. Может быть, что-то вроде этого?
SELECT o1.CustomerID
FROM orders o1 INNER JOIN orders o2 ON o1.CustomerID = o2.CustomerID
WHERE o1.EmployeeID = 5 AND o2.EmployeeID != 6
Упс, 525 строк. Может быть, добавить 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
Теперь это 28 рядов, все еще намного больше, чем мы получили с EXCEPT
. Причина в том, что это не удаляет CustomerID, которые сделали заказ с 6. Скорее, он возвращает все CustomerID, которые имеют заказ с 5 и некоторые EmployeeID, отличные от 6 или нет у них также есть заказ с EmployeeID 6.
Короче говоря, EXCEPT
и INTERSECT
- операторы множеств, которые сравнивают два запроса, возвращая уникальные кортежи, и, безусловно, их используют.