Non penso che abbia nulla a che fare con l'essere terribilmente lento; ha a che fare con l'essere potenzialmente inaccurati. Ad esempio, dati i seguenti dati - ordini che potrebbero essere effettuati da un singolo cliente o da un partner B2B:
DECLARE @Customers TABLE(CustomerID INT);
INSERT @Customers VALUES(1),(2);
DECLARE @Orders TABLE(OrderID INT, CustomerID INT, CompanyID INT);
INSERT @Orders VALUES(10,1,NULL),(11,NULL,5);
Diciamo che voglio trovare tutti i clienti che non hanno mai effettuato un ordine. Dati i dati, ce n'è solo uno: cliente n. 2. Ecco tre modi in cui potrei fare per scrivere una query per trovare quelle informazioni (ce ne sono altre):
SELECT [NOT IN] = CustomerID FROM @Customers
WHERE CustomerID NOT IN (SELECT CustomerID FROM @Orders);
SELECT [NOT EXISTS] = CustomerID FROM @Customers AS c
WHERE NOT EXISTS (SELECT 1 FROM @Orders AS o
WHERE o.CustomerID = c.CustomerID);
SELECT [EXCEPT] = CustomerID FROM @Customers
EXCEPT SELECT CustomerID FROM @Orders;
risultati:
NOT IN
------
-- <-- no results. Is that what you expected?
NOT EXISTS
----------
2
EXCEPT
------
2
Ora, ci sono anche alcuni problemi di prestazioni, e ne parlo in questo post sul blog . A seconda dei dati e degli indici, di NOT EXISTSsolito sovraperformerà NOT INe non so se potrebbe mai andare peggio. Dovresti anche notare che EXCEPTpuoi introdurre un'operazione di ordinamento distinta, quindi potresti finire con dati diversi (di nuovo, a seconda della fonte). E che il LEFT OUTER JOIN ... WHERE right.column IS NULLmodello popolare è sempre il peggiore.
Martin Smith ha anche molte buone informazioni di supporto nella sua risposta su SO .
IN/NOT INsarà sempre implementato con anelli annidati. E non ho idea di cosastops SQL Server from creating a ‘plan’dovrebbe significare.