Condizione all’interno di JOIN o DOVE

C’è qualche differenza (prestazioni, best-practice, ecc …) tra mettere una condizione nella clausola JOIN vs. la clausola WHERE?

Per esempio…

-- Condition in JOIN SELECT * FROM dbo.Customers AS CUS INNER JOIN dbo.Orders AS ORD ON CUS.CustomerID = ORD.CustomerID AND CUS.FirstName = 'John' -- Condition in WHERE SELECT * FROM dbo.Customers AS CUS INNER JOIN dbo.Orders AS ORD ON CUS.CustomerID = ORD.CustomerID WHERE CUS.FirstName = 'John' 

Quale preferisci (e forse perché)?

L’algebra relazionale consente l’intercambiabilità dei predicati nella clausola WHERE e INNER JOIN , quindi anche le query INNER JOIN con le clausole WHERE possono avere i predicati riorganizzati dall’ottimizzatore in modo che possano essere esclusi durante il processo JOIN .

Vi consiglio di scrivere le domande nel modo più leggibile ansible.

A volte ciò include rendere INNER JOIN relativamente “incompleto” e inserire alcuni dei criteri nel WHERE semplicemente per rendere gli elenchi dei criteri di filtro più facilmente mantenibili.

Ad esempio, invece di:

 SELECT * FROM Customers c INNER JOIN CustomerAccounts ca ON ca.CustomerID = c.CustomerID AND c.State = 'NY' INNER JOIN Accounts a ON ca.AccountID = a.AccountID AND a.Status = 1 

Scrivi:

 SELECT * FROM Customers c INNER JOIN CustomerAccounts ca ON ca.CustomerID = c.CustomerID INNER JOIN Accounts a ON ca.AccountID = a.AccountID WHERE c.State = 'NY' AND a.Status = 1 

Ma dipende, ovviamente.

Per i join interni non ho notato alcuna differenza (ma, come per tutte le prestazioni, è necessario controllare il database in base alle proprie condizioni).

Tuttavia, dove si inserisce la condizione fa una grande differenza se si utilizzano join a sinistra o a destra. Ad esempio, considera queste due domande:

 SELECT * FROM dbo.Customers AS CUS LEFT JOIN dbo.Orders AS ORD ON CUS.CustomerID = ORD.CustomerID WHERE ORD.OrderDate >'20090515' SELECT * FROM dbo.Customers AS CUS LEFT JOIN dbo.Orders AS ORD ON CUS.CustomerID = ORD.CustomerID AND ORD.OrderDate >'20090515' 

Il primo ti fornirà solo i record con un ordine datato oltre il 15 maggio 2009, convertendo quindi il join sinistro in un join interno. Il secondo darà quei record più eventuali clienti senza ordini. Il set di risultati è molto diverso a seconda di dove si imposta la condizione. (Selezionate * se, ad esempio, non doveste usare ovviamente nel codice di produzione.) L’eccezione è quando volete vedere solo i record in una tabella ma non nell’altra. Quindi si utilizza la clausola where per la condizione, non il join.

 SELECT * FROM dbo.Customers AS CUS LEFT JOIN dbo.Orders AS ORD ON CUS.CustomerID = ORD.CustomerID WHERE ORD.OrderID is null 

La maggior parte dei prodotti RDBMS ottimizzerà entrambe le query in modo identico. In “SQL Performance Tuning” di Peter Gulutzan e Trudy Pelzer, hanno testato diversi marchi di RDBMS e non hanno riscontrato differenze di prestazioni.

Preferisco mantenere le condizioni di partecipazione separate dalle condizioni di restrizione delle query.

Se stai usando OUTER JOIN volte è necessario inserire delle condizioni nella clausola join.

WHERE verrà filtrato dopo che si è verificato JOIN.

Filtra su JOIN per impedire l’aggiunta di righe durante il processo JOIN.

Preferisco il JOIN per unire tabelle / viste complete e quindi utilizzare il WHERE per introdurre il predicato del set risultante.

Sembra sintatticamente più pulito.

Di solito vedo un aumento delle prestazioni durante il filtraggio sul join. Soprattutto se puoi unirti su colonne indicizzate per entrambe le tabelle. Dovresti essere in grado di ridurre le letture logiche con la maggior parte delle query anche in questo caso, che è, in un ambiente ad alto volume, un indicatore di prestazioni molto migliore del tempo di esecuzione.

Sono sempre leggermente divertito quando qualcuno mostra il loro benchmark SQL e hanno eseguito entrambe le versioni di uno sproc 50.000 volte a mezzanotte sul server di sviluppo e confrontano i tempi medi.

Mettere la condizione nel join sembra “semanticamente sbagliato” per me, poiché non è quello che i JOIN sono “per”. Ma è molto qualitativo.

Ulteriore problema: se si decide di passare da un join interno a, ad esempio, a un join destro, se la condizione si trova all’interno di JOIN potrebbe portare a risultati imprevisti.

Le unioni sono più veloci secondo me quando hai un tavolo più grande. In realtà non è una gran differenza, specialmente se hai a che fare con un tavolo piuttosto piccolo. Quando ho appreso per la prima volta dei join, mi è stato detto che le condizioni nei join sono esattamente come le condizioni della clausola e che potrei usarle in modo intercambiabile se la clausola where fosse specifica su quale tabella eseguire la condizione.

È meglio aggiungere la condizione nel join. Le prestazioni sono più importanti della leggibilità. Per dataset di grandi dimensioni, è importante.