2009-06-10 4 views
2

Est-il vrai que quel que soit le type de jointure que vous utilisez, si votre clause WHERE vérifie la table fk d'une table, elle devient identique à une jointure interne tant que le jeu de résultats est connecté? En d'autres termes, si votre requête sql comporte des éléments comme:Est-il vrai que tous les types de jointures se réduisent à des jointures internes en présence de la vérification de fk d'une table?

"Sélectionnez ... à partir de A A jointure B Sur (...) E, F Jointure externe complète G sur (A.pk = G.fk) ... O WH A.pk = G.fk et A.pk = B.fk et etc ... "

Dans la requête ci-dessus, A est joint à gauche à B, alors que G est extérieurement joint à A sur son fk. Mais comme la clause where a les deux vérifications, toute la requête se réduit à quelque chose comme:

"Sélectionnez ... de A INNER JOIN B Sur (...) E, F INNER Rejoindre G on (A.pk = G.fk) ... OERE etc ... " ?

La raison de cette requête est que j'ai de nombreuses jointures de type cartésien ainsi que des clauses where sur la table fk d'une autre table, ce qui ralentit la requête. Je pensais remplacer les produits cartésiens par les deux Joints Gauche combinés avec le maintien de toutes les clauses where, ou de toutes les Jointures Inner.

Répondre

1

Oui si vous refernce le côté droit d'une jointure externe gauche dans une clause where avec n'importe quoi sauf "où myfield est nul", vous avez créé une jointure interne. C'est parce qu'il filtre tout ce qui ne remplit pas cette condition, y compris tous les enregistrements qui ne correspondent pas à la table intial. Pareil avec les autres jointures non internes. Pour contourner cela, vous mettez la condition dans la jointure.Exemple (ce transforme en une jointure interne):

Select field1, field2 from mytable mt 
left join mytable2 mt2 on mt.id = m2.id 
where mt1.field1 = 'hello' and mt2.field2 = 'test' 

réécrits pour préserver la gauche rejoindre:

Select field1, field2 from mytable mt 
left join mytable2 mt2 on mt.id = m2.id and mt2.field2 = 'test' 
where mt1.field1 = 'hello' 

Je veux aussi faire des commentaires sur quelque chose que vous avez dit dans un commentaire, mais FIGURED ma réponse serait trop long pour un autre commentaire. "Sélectionnez ... à partir d'une jointure interne B sur (A.id = B.a_id), C, D, F où A.id = F.id" à: "Sélectionnez ... A partir de A intérieur Joignez B sur (A.id = B.a_id), C, D INNER JOIN F sur A.id = F.a_id "

Vous ne voulez pas combiner des syntaxes de ce type; Cela devient très difficile à maintenir. En fait, je recommande de ne jamais utiliser l'ancienne syntaxe de virgule de style car elle est sujette à des jointures croisées accidentelles. Donc, dans votre exemple, je voudrais écrire pour obtenir le jeu de résultats que vous obtenez actuellement (au moins quelqu'un maintenant saura vous indended une jointure croisée au lieu de fait par hasard):

Select ... From A 
INNER JOIN B on A.id = B.a_id 
INNER JOIN F on A.id = F.a_id 
CROSS JOIN C 
CROSS JOIN D 

Altenatively si la jointure croisée est accidentelle, le code changerait à:

Select ... From A 
INNER JOIN B on A.id = B.a_id 
INNER JOIN F on A.id = F.a_id 
INNER JOIN C on (fill in the join fields) 
INNER JOIN D on (fill in the join fields) 
3

Oui, c'est un moyen indirect d'obtenir une jointure interne. Pensez à comment cela fonctionne: Il tire tout de A, puis les B correspondants ou null, puis tous les G (null sur les côtés A/B et G), puis il filtre essentiellement tout ce qui a un côté nul à lui (la clause WHERE). Donc, oui, le INNER JOIN est probablement plus rapide.

Une source commune de cette confusion est que ceci:

SELECT * FROM a INNER JOIN b ON a.id = b.id AND b.something = 'awesome' 

est équivalent à:

SELECT * FROM a INNER JOIN b ON a.id = b.id WHERE b.something = 'awesome' 

Cependant, cette même approche transitive ne fonctionne pas avec plein/jointures externes, comme fera la jointure puis filtrera (en fonction des filtres, bien sûr, et de l'optimiseur). Donc, en bref: utilisez des jointures internes si vous voulez vraiment une jointure interne. Editer: Je dois également noter que ce n'est pas l'accord PK/FK, c'est si vous répétez essentiellement votre clause ON dans la clause WHERE que les jointures full/outer deviendront équivalentes aux jointures internes.

+0

aussi, est-STH comme cet équivalent: « Select ... de A INNER JOIN B (A.id = B.a_id), C, D, F où A. id = F.id " à: " Sélectionnez ... A Une jointure interne B sur (A.id = B.a_id), C, D INNER JOIN F sur A.id = F.a_id " En fait, la question principale est que F a une jointure non pas avec D mais avec A, et A se produit beaucoup plus tôt dans l'expression, ainsi la jointure interne fonctionne correctement pour réduire les deux cas pour retourner le même resultset? – umar

1

Oui, et vous pouvez également ajouter simplement

"Where PK Is Not Null" or 
"Where FK Is Not Null" 

et ce serait également filtrer les enregistrements « supplémentaires » du côté « extérieur » de la jointure ...

Questions connexes