Condition dans JOIN ou WHERE

Y a-t-il une différence (performance, meilleures pratiques, etc.) entre la mise en condition de la clause JOIN et la clause WHERE?

Par exemple…

-- 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' 

Lequel préférez-vous (et peut-être pourquoi)?

L’algèbre relationnelle permet l’interchangeabilité des prédicats de la clause WHERE et de l’ INNER JOIN , de sorte que même les requêtes INNER JOIN avec clauses WHERE peuvent être réorganisées par l’optimiseur afin qu’elles puissent déjà être exclues lors du processus JOIN .

Je vous recommande d’écrire les requêtes de la manière la plus lisible possible.

Parfois, cela implique de rendre le INNER JOIN relativement «incomplet» et de placer certains des critères du WHERE simplement pour rendre les listes de critères de filtrage plus facilement maintenables.

Par exemple, au lieu de:

 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 

Écrire:

 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 

Mais ça dépend bien sûr.

Pour les jointures internes, je n’ai pas vraiment remarqué de différence (mais, comme pour tout réglage des performances, vous devez vérifier votre firebase database dans vos conditions).

Cependant, si vous mettez la condition, cela fait une énorme différence si vous utilisez des jointures gauche ou droite. Par exemple, considérez ces deux requêtes:

 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' 

Le premier ne vous donnera que les enregistrements dont l’ordre est postérieur au 15 mai 2009, convertissant ainsi la jointure gauche en jointure interne. Le second donnera ces enregistrements plus tous les clients sans commandes. L’ensemble de résultats est très différent selon l’endroit où vous avez placé la condition. (Sélectionnez * si à titre d’exemple uniquement, vous ne devez pas utiliser bien sûr le code de production.) La seule exception est lorsque vous voulez voir uniquement les enregistrements d’une table mais pas de l’autre. Ensuite, vous utilisez la clause where pour la condition et non la jointure.

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

La plupart des produits SGBDR optimiseront les deux requêtes de manière identique. Dans “SQL Performance Tuning” de Peter Gulutzan et Trudy Pelzer, ils ont testé plusieurs marques de SGBDR et n’ont constaté aucune différence de performance.

Je préfère garder les conditions de jointure séparées des conditions de ressortingction de requête.

Si vous utilisez OUTER JOIN il est parfois nécessaire de mettre des conditions dans la clause de jointure.

WHERE va filtrer après que la jointure s’est produite.

Filtrer sur la jointure pour empêcher l’ajout de lignes pendant le processus JOIN.

Je préfère que JOIN se joigne à des tables / vues complètes et utilise ensuite WHERE Pour introduire le prédicat de l’ensemble résultant.

Il se sent syntaxiquement plus propre.

Je constate généralement une augmentation des performances lors du filtrage sur la jointure. Surtout si vous pouvez vous joindre à des colonnes indexées pour les deux tables. Vous devriez être capable de réduire les lectures logiques avec la plupart des requêtes, ce qui est, dans un environnement à fort volume, un indicateur de performance bien meilleur que le temps d’exécution.

Je suis toujours légèrement amusé quand quelqu’un montre son parsing SQL et qu’il a exécuté les deux versions d’un sproc 50 000 fois à minuit sur le serveur de développement et comparé les temps moyens.

Mettre la condition dans la jointure me semble “sémantiquement fausse”, car ce n’est pas ce que les JOIN sont “pour”. Mais c’est très qualitatif.

Problème supplémentaire: si vous décidez de passer d’une jointure interne à une jointure droite, par exemple, le fait que la condition soit à l’intérieur de la jointure peut entraîner des résultats inattendus.

Les jointures sont plus rapides à mon avis lorsque vous avez une table plus grande. Ce n’est vraiment pas une grande différence, surtout si vous avez affaire à un tableau plus petit. Quand j’ai appris pour la première fois les jointures, on m’a dit que les conditions dans les jointures étaient comme les conditions de clause where et que je pouvais les utiliser indifféremment si la clause where était spécifique sur la table sur laquelle la condition devait être exécutée.

Il est préférable d’append la condition dans la jointure. La performance est plus importante que la lisibilité. Pour les grands ensembles de données, c’est important.