Quelle est la raison de l'utilisation de la double jointure interne dans cette instruction SQL?


10

Je regarde cette requête SQL héritée. Le bit que je ne suis pas en mesure d'obtenir est la raison pour laquelle il est interne de joindre deux fois la même table sur les mêmes colonnes. Je parle de Table1 et Table1 joint à l'alias "Table1Alias",

SELECT DISTINCT othercolumns,
                Table1Alias.columna
FROM   maintable
       INNER JOIN secondarytable
               ON maintable.id1 = secondarytable.a_id1
       INNER JOIN table1
               ON secondarytable.id2 = table1.id3
       INNER JOIN table1 Table1Alias
               ON secondarytable.id2 = Table1Alias.id3
       INNER JOIN thirdtable
               ON table1.id4 = thirdtable.id5
       INNER JOIN fourthtable
               ON thirdtable.id6 = fourthtable.id7
       INNER JOIN fivetable
               ON thirdtable.id8 = fivetable.id9
       INNER JOIN sixthtable
               ON Table1Alias.columna = sixthtable.id10
       LEFT JOIN seventhtable
              ON thirdtable.id11 = seventhtable.id12
WHERE  LEFT(secondarytable.type123, 2) BETWEEN '01' AND '09'
       AND secondarytable.type456 = 'cate'
       AND table1.type = '0'
       AND Table1Alias.columna = 'conn'

Réponses:


27

Cela pourrait aider à réécrire la requête comme ceci, il est donc évident que les 2 jointures sont différentes , c'est-à-dire que les jointures sont à différents sous-ensembles (de la même table):

FROM   maintable 
       INNER JOIN secondarytable 
               ON maintable.id1 = secondarytable.a_id1 
       INNER JOIN table1 
               ON secondarytable.id2 = table1.id3 
              AND table1.type = '0' 
       INNER JOIN table1 Table1Alias 
               ON secondarytable.id2 = Table1Alias.id3 
              AND Table1Alias.columna = 'conn' 
       INNER JOIN
       ...
WHERE  LEFT(secondarytable.type123, 2) BETWEEN '01' AND '09' 
       AND secondarytable.type456 = 'cate' 

n'est pas le WHERE à appliquer APRÈS les jointures, c'est-à-dire que je serais d'accord si ces contraintes faisaient partie de l'instruction join, c'est-à-dire connectées par un ET, mais le WHERE dans toute l'expérience est appliqué au résultat de la jointure filtrant les lignes de la table jointe, sans influencer la jointure réelle.
Frank Hopkins

3
@Darkwing Pour autant que je sache, peu importe où vous mettez les conditions, car c'est le travail de l'optimiseur de requêtes de trouver le meilleur plan d'exceution. Cependant, il est préférable de les placer à côté des jointures car cela les rend plus lisibles, mais ce n'est qu'une opinion
Mathématiques

Même si cela devait arriver APRÈS avoir rejoint les résultats, les résultats des jointures sont finalement différents. Et oui, les lignes jointes sont généralement filtrées avant d'être jointes car cela améliore les performances.
Gherman

1
Cela équivaut également à se joindre à une sous-requête, par exemple INNER JOIN (SELECT * FROM table1 WHERE type = 0) table1. Cela pourrait rendre encore plus évident ce qui se passe.
Barmar

3
@Mathematics - qu'une condition se trouve dans la ONclause d'une jointure ou dans la WHEREclause peut être très importante si la jointure est un OUTER JOIN. Si une condition échoue dans la ONclause, la ligne principale est toujours incluse (sans ligne externe correspondante); s'il échoue dans la WHEREclause, la ligne principale est exclue du jeu de résultats.
RDFozz

8

En regardant la whereclause, la ligne pointée par table1requiert la colonne type= = 0 et la ligne pointée par table1aliasrequiert la colonne columna= = conn.

Peut-être qu'il y a plusieurs lignes table1pour le même id3?


2

Sans voir la structure de la table - l'approche pourrait être d'utiliser un index non couvrant plus petit, puis de se joindre à la table sur un index couvrant plus grand pour obtenir le reste des lignes afin d'éviter une opération de recherche de clé et d'éviter de modifier les index existants (ou si vous ne pouvez pas modifier les index)


2

Chaque fois qu'une table apparaît plus d'une fois dans une jointure complexe, c'est généralement parce qu'il existe une entité qui participe à plusieurs relations. Cela semble être le cas ici, à en juger par la réponse donnée par @Ypercube.

Les entités et les relations sont généralement comprises à travers la sémantique des données et la connexion au sujet sous-jacent. Si votre ancien système a été construit avec soin, ils ont probablement pris un certain soin pour analyser le sujet et définir soigneusement chacun des éléments de données. Ils peuvent même avoir construit un modèle Entité-Relation. Tout ce travail minutieux a peut-être été perdu, et vous êtes en train de le reconstruire en creusant dans le passé. C'est un peu comme l'archéologie.

Avec des noms de table comme Table1, nous n'avons aucune idée du fonctionnement de votre sujet. Et même si les noms étaient descriptifs, notre compréhension du sujet de votre système peut être très différente de ce qui est nécessaire dans votre cas. Cela dépendra de vous.

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.