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


189

Sans tenir compte des performances, vais-je obtenir le même résultat des requêtes A et B ci-dessous? Que diriez-vous de 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
Quoi <blahblah>? vous joignez A à B et A à C, ou vous joignez A à B et B à C?
beny23

2
Salut Beny, le code de ma question est une abstraction. Je ne suis pas préoccupé par la jonction de A à B ou de A à C, je veux juste savoir si la syntaxe comme celle-ci fournira des résultats identiques.
Juste un apprenant

Réponses:


225

Pour les INNERjointures, non, l'ordre n'a pas d'importance. Les requêtes renverront les mêmes résultats, tant que vous modifiez vos sélections de SELECT *à SELECT a.*, b.*, c.*.


Pour ( LEFT, RIGHTou FULL) les OUTERjointures, oui, les questions d'ordre - et ( mises à jour ) les choses sont beaucoup plus compliquées.

Premièrement, les jointures externes ne sont pas commutatives, ce a LEFT JOIN bn'est donc pas la même chose queb LEFT JOIN a

Les jointures externes ne sont pas associatives non plus, donc dans vos exemples qui impliquent à la fois les 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

équivaut à :

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é (espérons-le plus simple). Considérez cela 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

Cela équivaut à 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 ONconditions «agréables» . Les deux ON b.ab_id = a.ab_idet c.bc_id = b.bc_idsont des contrôles d'égalité et n'impliquent pas de NULLcomparaisons.

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

Cependant, si l'un de ces éléments était impliqué IS NULLou une fonction liée à des valeurs nulles comme COALESCE(), par exemple, si la condition l'était b.ab_id IS NULL, les deux requêtes ne seraient pas équivalentes.


3
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 valeurs nulles'. On peut facilement imaginer un prédicat qui satisfait la première description mais pas la seconde, comme a.somecol > 0 OR b.someothercol > 0; l'associativité pourrait échouer pour cette condition.
Mark Amery

Mais oui, je pense qu'il est techniquement vrai de dire que OUTER JOIN est associatif tant que le prédicat ne satisfait aucune des conditions que je décris ici: stackoverflow.com/questions/20022196/… (le premier casse également l'associativité pour INNER JOINs, mais est une approche tellement peu coûteuse et évidente pour le casser que cela ne vaut peut-être pas la peine de le mentionner.) Il convient également de souligner que le type le plus courant de JOIN - JOIN sur une clé étrangère - ne satisfait à aucune de ces conditions et est donc agréable et associatif.
Mark Amery

1
@MarkAmery Merci, j'avais du mal à structurer mes phrases sur ce point (et j'ai déjà voté pour votre réponse;)
ypercubeᵀᴹ

ypercube j'ai un INNER JOINet un suivant LEFT JOIN. Est-ce que cela fonctionne comme ça d'abord la requête sera Filterles enregistrements sur la base de INNER JOIN, puis s'appliquera LEFT JOINaux Filteredenregistrements?
Muhammad Babar

En fait, tous les types de jointure sont associatifs, comme spécifié par la norme SQL et selon les définitions mathématiques de l'associativité, mais ils ne semblent pas associatifs car la réorganisation des parenthèses nécessite de déplacer la ONclause (c'est-à-dire la "spécification de jointure") vers un nouvel emplacement . Ce n'est cependant que de la syntaxe. Si vous utilisez la notation d'algèbre relationnelle (où la spécification de jointure est placée sous l'opérateur de jointure), l'associativité devient plus évidente. Votre argument montre seulement que les jointures externes ne sont pas commutatives , ce qui est correct
Lukas Eder

4

pour les jointures régulières, ce n'est pas le cas. TableA join TableBproduira 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, c'est le cas. TableA left Join TableBest différent de TableB left Join TableA, MAIS c'est le même queTableB right Join TableA


4
Cela ne concerne que la commutativité, mais les exemples de la question montrent que le demandeur s'intéresse à l'associativité. La réponse de ypercube aborde les deux.
Mark Amery

2

Si vous essayez de joindre C sur un champ de B avant de rejoindre 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 est important.


Oui, c'est vrai, la bonne réponse doit être modifiée.
Nir Pengas

-2

L'optimiseur Oracle choisit l'ordre de jointure des tables pour la jointure interne. L'optimiseur choisit l'ordre de jointure des tables uniquement dans des clauses FROM simples. Vous pouvez consulter la documentation d'Oracle sur leur 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 quel index 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 des clauses FROM simples. La plupart des jointures utilisant le mot clé JOIN sont aplaties en jointures simples, de sorte que l'optimiseur choisit 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 Si un index sur une table est utile dans un ordre de jointure particulier Le nombre de lignes et de pages à analyser pour chaque table dans chaque ordre de jonction

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.