En SQL, j'essaie de filtrer les résultats en fonction d'un ID et je me demande s'il y a une différence logique entre
SELECT value
FROM table1
JOIN table2 ON table1.id = table2.id
WHERE table1.id = 1
et
SELECT value
FROM table1
JOIN table2 ON table1.id = table2.id AND table1.id = 1
Pour moi, il semble que la logique soit différente bien que vous obtiendrez toujours le même ensemble de résultats, mais je me demandais s'il y avait des conditions dans lesquelles vous obtiendriez deux ensembles de résultats différents (ou renverraient-ils toujours exactement les deux mêmes ensembles de résultats )
La réponse est [~ # ~] pas de différence [~ # ~] , mais:
Je préférerai toujours faire ce qui suit.
ON
where
Cela rend la requête plus lisible .
Je vais donc utiliser cette requête:
SELECT value
FROM table1
INNER JOIN table2
ON table1.id = table2.id
WHERE table1.id = 1
Cependant, lorsque vous utilisez OUTER JOIN'S
il y a une grande différence à garder le filtre dans les conditions ON
et Where
.
Traitement logique des requêtes
La liste suivante contient une forme générale de requête, ainsi que des numéros d'étape attribués selon l'ordre dans lequel les différentes clauses sont traitées logiquement.
(5) SELECT (5-2) DISTINCT (5-3) TOP(<top_specification>) (5-1) <select_list>
(1) FROM (1-J) <left_table> <join_type> JOIN <right_table> ON <on_predicate>
| (1-A) <left_table> <apply_type> APPLY <right_table_expression> AS <alias>
| (1-P) <left_table> PIVOT(<pivot_specification>) AS <alias>
| (1-U) <left_table> UNPIVOT(<unpivot_specification>) AS <alias>
(2) WHERE <where_predicate>
(3) GROUP BY <group_by_specification>
(4) HAVING <having_predicate>
(6) ORDER BY <order_by_list>;
Diagramme de flux de traitement logique
(1) FROM: la phase FROM identifie les tables source de la requête et traite les opérateurs de table. Chaque opérateur de table applique une série de sous-phases. Par exemple, les phases impliquées dans une jointure sont (1-J1) un produit cartésien, (1-J2) ON Filter, (1-J3) Add Outer Rows. La phase FROM génère la table virtuelle VT1.
(1-J1) Produit cartésien: Cette phase effectue un produit cartésien (jointure croisée) entre les deux tables impliquées dans l'opérateur de table, générant VT1-J1.
Il fait référence à cet excellent lien.
Bien qu'il n'y ait aucune différence lors de l'utilisation de INNER JOINS, comme l'a souligné VR46, il existe une différence significative lors de l'utilisation de OUTER JOINS et de l'évaluation d'une valeur dans le deuxième tableau (pour les jointures de gauche - première table pour les jointures droites). Considérez la configuration suivante:
DECLARE @Table1 TABLE ([ID] int)
DECLARE @Table2 TABLE ([Table1ID] int, [Value] varchar(50))
INSERT INTO @Table1
VALUES
(1),
(2),
(3)
INSERT INTO @Table2
VALUES
(1, 'test'),
(1, 'hello'),
(2, 'goodbye')
Si nous le sélectionnons en utilisant une jointure externe gauche et mettons une condition dans la clause where:
SELECT * FROM @Table1 T1
LEFT OUTER JOIN @Table2 T2
ON T1.ID = T2.Table1ID
WHERE T2.Table1ID = 1
Nous obtenons les résultats suivants:
ID Table1ID Value
----------- ----------- --------------------------------------------------
1 1 test
1 1 hello
Cela est dû au fait que la clause where limite l'ensemble de résultats, nous n'incluons donc que les enregistrements de table1 qui ont un ID de 1. Cependant, si nous déplaçons la condition dans la clause on:
SELECT * FROM @Table1 T1
LEFT OUTER JOIN @Table2 T2
ON T1.ID = T2.Table1ID
AND T2.Table1ID = 1
Nous obtenons les résultats suivants:
ID Table1ID Value
----------- ----------- --------------------------------------------------
1 1 test
1 1 hello
2 NULL NULL
3 NULL NULL
En effet, nous ne filtrons plus l'ensemble de résultats par l'ID 1 de la table1 - nous filtrons plutôt le JOIN. Ainsi, même si l'ID de table1 de 2 a une correspondance dans la deuxième table, il est exclu de la jointure - mais PAS l'ensemble de résultats (d'où les valeurs nulles).
Ainsi, pour les jointures internes, cela n'a pas d'importance, mais vous devez le conserver dans la clause where pour plus de lisibilité et de cohérence. Cependant, pour les jointures externes, vous devez être conscient que cela importe où vous placez la condition car cela affectera votre jeu de résultats.
Je pense que la réponse marquée "droite" n'est pas correcte. Pourquoi? J'essaie d'expliquer:
Nous avons une opinion
"Gardez toujours la clause Join Conditions in ON Mettez toujours le filtre dans la clause where"
Et c'est faux. Si vous êtes dans la jointure interne, mettez à chaque fois les paramètres de filtre dans la clause ON, pas dans où. Vous demandez pourquoi? Essayez d'imaginer une requête complexe avec un total de 10 tables (c'est-à-dire que chaque table a 10 000 enregistrements), avec la clause WHERE complexe (par exemple, les fonctions ou les calculs utilisés). Si vous placez des critères de filtrage dans la clause ON, JOINS entre ces 10 tables ne se produit pas, la clause WHERE ne sera pas exécutée du tout. Dans ce cas, vous n'effectuez pas 10000 ^ 10 calculs dans la clause WHERE. Cela a du sens, ne pas placer les paramètres de filtrage dans la clause WHERE uniquement.