239 votes

L'ordre de jointure est-il important en SQL ?

Sans tenir compte des performances, est-ce que j'obtiendrai le même résultat avec les requêtes A et B ci-dessous ? Et avec C et D ?

-- A
select *
from   a left join b
           on <blahblah>
       left join c
           on <blahblan>

-- B
select *
from   a left join c
           on <blahblah>
       left join b
           on <blahblan>  

-- C
select *
from   a join b
           on <blahblah>
       join c
           on <blahblan>

-- D
select *
from   a join c
           on <blahblah>
       join b
           on <blahblan>

11 votes

Qu'est-ce que <blahblah> ? est-ce que vous joignez A à B et A à C, ou est-ce que vous joignez A à B et B à C ?

3 votes

Bonjour Beny, le code dans ma question est une abstraction. Je ne me préoccupe pas de joindre A à B ou A à C, je veux juste savoir si une telle syntaxe donnera des résultats identiques.

279voto

ypercube Points 62714

Pour INNER rejoint, non, l'ordre n'a pas d'importance. Les requêtes retourneront les mêmes résultats, tant que vous changez vos selects de SELECT * a SELECT a.*, b.*, c.* .


Pour ( LEFT , RIGHT o FULL ) OUTER rejoint, oui, l'ordre importe - et ( actualisé ) les choses sont beaucoup plus compliquées.

Premièrement, les jointures externes ne sont pas commutatives, donc a LEFT JOIN b n'est pas la même chose que b LEFT JOIN a

Les jointures externes ne sont pas non plus associatives, donc dans vos exemples qui impliquent les deux propriétés (commutativité et associativité) :

a LEFT JOIN b 
    ON b.ab_id = a.ab_id
  LEFT JOIN c
    ON c.ac_id = a.ac_id

est équivalent à :

a LEFT JOIN c 
    ON c.ac_id = a.ac_id
  LEFT JOIN b
    ON b.ab_id = a.ab_id

mais :

a LEFT JOIN b 
    ON  b.ab_id = a.ab_id
  LEFT JOIN c
    ON  c.ac_id = a.ac_id
    AND c.bc_id = b.bc_id

n'est pas équivalent à :

a LEFT JOIN c 
    ON  c.ac_id = a.ac_id
  LEFT JOIN b
    ON  b.ab_id = a.ab_id
    AND b.bc_id = c.bc_id

Un autre exemple d'associativité (plus simple, espérons-le). Considérez ceci comme (a LEFT JOIN b) LEFT JOIN c :

a LEFT JOIN b 
    ON b.ab_id = a.ab_id          -- AB condition
 LEFT JOIN c
    ON c.bc_id = b.bc_id          -- BC condition

Ce site est équivalent a a LEFT JOIN (b LEFT JOIN c) :

a LEFT JOIN  
    b LEFT JOIN c
        ON c.bc_id = b.bc_id          -- BC condition
    ON b.ab_id = a.ab_id          -- AB condition

seulement parce que nous avons des "gentils" ON conditions. Les deux sites ON b.ab_id = a.ab_id y c.bc_id = b.bc_id sont des contrôles d'égalité et n'impliquent pas NULL comparaisons.

Vous pouvez même avoir des conditions avec d'autres opérateurs ou des conditions plus complexes comme : ON a.x <= b.x o ON a.x = 7 o ON a.x LIKE b.x o ON (a.x, a.y) = (b.x, b.y) et les deux requêtes seraient toujours équivalentes.

Si toutefois, l'un de ces éléments IS NULL ou une fonction qui est liée aux nuls comme COALESCE() par exemple, si la condition était b.ab_id IS NULL alors les deux requêtes ne seraient pas équivalentes.

3 votes

Il est plus correct de dire que la jointure externe est associative tant qu'aucun des prédicats ne peut être satisfait par une ligne dans laquelle toutes les colonnes d'une table sont NULL, que de dire qu'elle est associative tant que les prédicats n'impliquent pas IS NULL ou "une fonction liée aux nuls". On peut facilement imaginer un prédicat qui satisfait à la première description mais pas à la seconde, par exemple a.somecol > 0 OR b.someothercol > 0 l'associativité pourrait échouer pour cette condition.

0 votes

Mais oui, je pense qu'il est techniquement vrai de dire que OUTER JOIN est associatif tant que le prédicat ne satisfait pas à l'une des conditions que je décris ici : stackoverflow.com/questions/20022196/ (la première d'entre elles casse également l'associativité pour les INNER JOINs, mais il s'agit d'une approche tellement bon marché et évidente pour la casser que cela ne vaut peut-être pas la peine d'être mentionné). Il est également utile de souligner que le type de JOIN le plus commun - JOINing sur une clé étrangère - ne satisfait aucune de ces conditions et est donc agréable et associatif.

1 votes

@MarkAmery Merci, j'avais du mal à structurer mes phrases sur ce point (et j'ai déjà upvoted cette réponse de votre part ;)

7voto

Teo J. Points 89

Si vous essayez de joindre C sur un champ de B avant de joindre B, c'est-à-dire :

SELECT A.x, 
       A.y, 
       A.z 
FROM A 
   INNER JOIN C
       on B.x = C.x
   INNER JOIN B
       on A.x = B.x

votre requête échouera, donc dans ce cas l'ordre importe.

5voto

Diego Points 13953

Pour les Joins réguliers, ce n'est pas le cas. TableA join TableB produira le même plan d'exécution que TableB join TableA (donc vos exemples C et D seraient les mêmes)

pour les jointures gauche et droite, ça le fait. TableA left Join TableB est différent de TableB left Join TableA MAIS c'est la même chose que TableB right Join TableA

5 votes

Cette réponse ne traite que de la commutativité, mais les exemples de la question montrent que le demandeur s'intéresse à l'associativité. La réponse de ypercube traite des deux.

3voto

Saumyojit Das Points 51

Optimiseur Oracle choisit l'ordre de jointure des tables pour la jointure interne. L'optimiseur choisit l'ordre de jointure des tables uniquement dans les clauses FROM simples. Vous pouvez consulter la documentation d'Oracle sur son site Web. Et pour la jointure externe gauche, droite, la réponse la plus votée est la bonne. L'optimiseur choisit l'ordre de jointure optimal ainsi que l'index optimal pour chaque table. L'ordre de jointure peut affecter l'index qui est le meilleur choix. L'optimiseur peut choisir un index comme chemin d'accès pour une table s'il s'agit de la table interne, mais pas s'il s'agit de la table externe (et il n'y a pas d'autres qualifications).

L'optimiseur choisit l'ordre de jointure des tables uniquement dans les clauses FROM simples. La plupart des jointures utilisant le mot-clé JOIN sont aplaties en jointures simples, et l'optimiseur choisit donc leur ordre de jointure.

L'optimiseur ne choisit pas l'ordre de jointure pour les jointures externes ; il utilise l'ordre spécifié dans l'instruction.

Lors de la sélection d'un ordre de jointure, l'optimiseur prend en compte : La taille de chaque table Les index disponibles sur chaque table l'utilité d'un index sur une table dans un ordre de jointure particulier le nombre de lignes et de pages à analyser pour chaque table dans chaque ordre de jointure.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X