web-dev-qa-db-fra.com

Jointure à gauche ou sélection de plusieurs tables en utilisant une virgule (,)

Je suis curieux de savoir pourquoi nous devons utiliser LEFT JOIN puisque nous pouvons utiliser des virgules pour sélectionner plusieurs tables.

Quelles sont les différences entre LEFT JOIN et l’utilisation de virgules pour sélectionner plusieurs tables.

Lequel est le plus rapide?

Voici mon code:

   SELECT mw.*, 
          nvs.* 
     FROM mst_words mw 
LEFT JOIN (SELECT no as nonvs, 
                  owner, 
                  owner_no, 
                  vocab_no, 
                  correct 
             FROM vocab_stats 
            WHERE owner = 1111) AS nvs ON mw.no = nvs.vocab_no 
    WHERE (nvs.correct > 0 ) 
      AND mw.level = 1

...et:

SELECT * 
  FROM vocab_stats vs, 
       mst_words mw 
 WHERE mw.no = vs.vocab_no 
   AND vs.correct > 0 
   AND mw.level = 1 
   AND vs.owner = 1111
14
bbnn

Tout d'abord, pour être complètement équivalent, la première requête aurait dû être écrite

   SELECT mw.*, 
          nvs.* 
     FROM mst_words mw 
LEFT JOIN (SELECT *
             FROM vocab_stats 
            WHERE owner = 1111) AS nvs ON mw.no = nvs.vocab_no 
    WHERE (nvs.correct > 0 ) 
      AND mw.level = 1

Ainsi, mw. * Et nvs. * Produisent ensemble le même ensemble que le singulier de la deuxième requête *. La requête telle que vous l'avez écrite peut utiliser un INNER JOIN, car elle inclut un filtre sur nvs.correct.

La forme générale

TABLEA LEFT JOIN TABLEB ON <CONDITION>

attempts pour rechercher des enregistrements TableB en fonction de la condition. En cas d'échec, les résultats de TABLEA sont conservés et toutes les colonnes de TableB sont définies sur NULL. En revanche

TABLEA INNER JOIN TABLEB ON <CONDITION>

également attempts pour rechercher des enregistrements TableB en fonction de la condition. Cependant, en cas d'échec, l'enregistrement de TableA est supprimé du jeu de résultats en sortie.

La norme ANSI pour CROSS JOIN produit un produit cartésien entre les deux tables.

TABLEA CROSS JOIN TABLEB
  -- # or in older syntax, simply using commas
TABLEA, TABLEB

L'intention de la syntaxe est que chaque ligne de TABLEA soit jointe à chaque ligne de TABLEB. Donc 4 lignes sur A et 3 lignes sur B produisent 12 lignes de sortie. Lorsqu'il est associé à des conditions dans la clause WHERE, il se produit parfois le même comportement de INNER JOIN, car elles expriment la même chose (condition entre A et B => keep ou non). Toutefois, la lecture de l'intention est plus claire lorsque vous utilisez INNER JOIN au lieu de virgules.

En termes de performances, la plupart des SGBD traitent une jointure LEFT plus rapidement qu’un INNER JOIN. La notation par virgule peut amener les systèmes de base de données à mal interpréter l’intention et à produire un plan de requête incorrect, un avantage supplémentaire pour la notation SQL92.

Pourquoi avons-nous besoin de LEFT JOIN? Si l'explication de LEFT JOIN ci-dessus n'est toujours pas suffisante (conserver les enregistrements en A sans les correspondances en B), alors considérez que pour obtenir la même chose, vous auriez besoin d'une union complexe entre deux ensembles utilisant l'ancienne notation par virgule même effet. Mais comme indiqué précédemment, cela ne s'applique pas à votre exemple, qui est en réalité un INNER JOIN se cachant derrière un LEFT JOIN.

Remarques:

  • RIGHT JOIN est identique à LEFT, sauf qu'il commence par TABLEB (côté droit) au lieu de A.
  • RIGHT et LEFT JOINS sont les deux jointures OUTER. Le mot OUTER est facultatif, c’est-à-dire qu’il peut s’écrire sous la forme LEFT OUTER JOIN.
  • Le troisième type de jointure OUTER est la jointure FULL OUTER, mais cela n’est pas abordé ici.
4
RichardTheKiwi

La séparation de JOIN et de WHERE facilite la lecture, car la logique de jointure ne peut être confondue avec les conditions WHERE. Ce sera généralement plus rapide car le serveur n'aura pas besoin de mener deux requêtes distinctes et de combiner les résultats.

Les deux exemples que vous avez donnés ne sont pas vraiment équivalents, car vous avez inclus une sous-requête dans le premier exemple. Ceci est un meilleur exemple:

SELECT vs.*, mw.*
FROM vocab_stats vs, mst_words mw
LEFT JOIN vocab_stats vs ON mw.no = vs.vocab_no
WHERE vs.correct > 0 
AND mw.level = 1
AND vs.owner = 1111
0
Bazmatiq