La plupart des dialectes SQL acceptent les deux requêtes suivantes:
SELECT a.foo, b.foo
FROM a, b
WHERE a.x = b.x
SELECT a.foo, b.foo
FROM a
LEFT JOIN b ON a.x = b.x
Maintenant, évidemment, lorsque vous avez besoin d'une jointure externe, la deuxième syntaxe est requise. Mais lorsque je fais une jointure interne, pourquoi devrais-je préférer la deuxième syntaxe à la première (ou vice versa)?
Réponses:
L'ancienne syntaxe, avec juste la liste des tables et l'utilisation de la
WHERE
clause pour spécifier les critères de jointure, est obsolète dans la plupart des bases de données modernes.Ce n'est pas seulement pour le show, l'ancienne syntaxe a la possibilité d'être ambiguë lorsque vous utilisez les jointures INNER et OUTER dans la même requête.
Laisse moi te donner un exemple.
Supposons que vous ayez 3 tables dans votre système:
Chaque table contient de nombreuses lignes, liées entre elles. Vous avez plusieurs entreprises, et chaque entreprise peut avoir plusieurs départements, et chaque département peut avoir plusieurs employés.
Ok, alors maintenant vous voulez faire ce qui suit:
Vous faites donc ceci:
Notez que le dernier il y a une jointure interne, afin de remplir les critères que vous ne voulez que des départements avec des personnes.
Ok, alors qu'est-ce qui se passe maintenant. Eh bien, le problème est que cela dépend du moteur de base de données, de l'optimiseur de requêtes, des index et des statistiques de table. Laisse-moi expliquer.
Si l'optimiseur de requêtes détermine que la façon de procéder consiste à prendre d'abord une entreprise, puis à trouver les services, puis à effectuer une jointure interne avec les employés, vous n'obtiendrez aucune entreprise qui n'a pas de service.
La raison en est que la
WHERE
clause détermine quelles lignes se retrouvent dans le résultat final, et non des parties individuelles des lignes.Et dans ce cas, en raison de la jointure gauche, la colonne Department.ID sera NULL, et donc en ce qui concerne la jointure interne à l'employé, il n'y a aucun moyen de respecter cette contrainte pour la ligne Employé, et donc ce ne sera pas le cas. apparaître.
En revanche, si l'optimiseur de requêtes décide d'aborder la jointure département-employé, puis de faire une jointure gauche avec les entreprises, vous les verrez.
L'ancienne syntaxe est donc ambiguë. Il n'y a aucun moyen de spécifier ce que vous voulez, sans traiter des indices de requête, et certaines bases de données n'ont aucun moyen.
Entrez la nouvelle syntaxe, avec celle que vous pouvez choisir.
Par exemple, si vous voulez toutes les entreprises, comme l'indique la description du problème, voici ce que vous écririez:
Ici, vous spécifiez que vous souhaitez que la jointure département-employé se fasse en une seule jointure, puis vous laissez les résultats de cette jointure avec les entreprises.
De plus, supposons que vous ne souhaitiez que les départements contenant la lettre X dans leur nom. Encore une fois, avec les jointures à l'ancienne, vous risquez également de perdre la société, si elle n'a pas de départements avec un X dans son nom, mais avec la nouvelle syntaxe, vous pouvez le faire:
Cette clause supplémentaire est utilisée pour la jointure, mais n'est pas un filtre pour la ligne entière. Ainsi, la ligne peut apparaître avec des informations sur la société, mais peut avoir des valeurs NULL dans toutes les colonnes département et employé pour cette ligne, car il n'y a pas de département avec un X dans son nom pour cette société. C'est difficile avec l'ancienne syntaxe.
C'est pourquoi, entre autres fournisseurs, Microsoft a déconseillé l'ancienne syntaxe de jointure externe, mais pas l'ancienne syntaxe de jointure interne, depuis SQL Server 2005 et versions ultérieures. La seule façon de parler à une base de données exécutée sur Microsoft SQL Server 2005 ou 2008, en utilisant l'ancienne syntaxe de jointure externe, est de définir cette base de données en mode de compatibilité 8.0 (alias SQL Server 2000).
De plus, l'ancienne méthode, en lançant un tas de tables sur l'optimiseur de requête, avec un tas de clauses WHERE, revenait à dire "vous voici, faites de votre mieux". Avec la nouvelle syntaxe, l'optimiseur de requêtes a moins de travail à faire pour comprendre quelles parties vont ensemble.
Alors voilà.
LEFT and INNER JOIN est la vague du futur.
la source
OUTER JOIN
syntaxe jamais standard*=
/=*
/*=*
est déconseillée.La syntaxe JOIN conserve les conditions près de la table à laquelle elles s'appliquent. Cela est particulièrement utile lorsque vous joignez un grand nombre de tables.
Soit dit en passant, vous pouvez également effectuer une jointure externe avec la première syntaxe:
Ou
Ou
la source
La première est l'ancienne norme. La deuxième méthode a été introduite dans SQL-92, http://en.wikipedia.org/wiki/SQL . La norme complète peut être consultée sur http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt .
Il a fallu de nombreuses années avant que les sociétés de bases de données adoptent la norme SQL-92.
Donc, la raison pour laquelle la deuxième méthode est préférée, c'est la norme SQL selon le comité des normes ANSI et ISO.
la source
,
est toujours standard.on
ne devaient être introduites que pourouter join
une fois les sous-sélections introduites.Fondamentalement, lorsque votre clause FROM répertorie des tables comme ceci:
le résultat est un produit croisé de toutes les lignes des tableaux A, B, C. Ensuite, vous appliquez la restriction
WHERE tableA.id = tableB.a_id
qui jettera un grand nombre de lignes, puis plus loin ...AND tableB.id = tableC.b_id
et vous ne devriez alors obtenir que les lignes qui vous intéressent vraiment dans.Les SGBD savent comment optimiser ce SQL afin que la différence de performances par rapport à l'écriture à l'aide de JOIN soit négligeable (le cas échéant). L'utilisation de la notation JOIN rend l'instruction SQL plus lisible (à mon humble avis, ne pas utiliser de jointures transforme l'instruction en désordre). En utilisant le produit croisé, vous devez fournir des critères de jointure dans la clause WHERE, et c'est le problème avec la notation. Vous encombrez votre clause WHERE avec des trucs comme
qui est uniquement utilisé pour restreindre le produit croisé. La clause WHERE ne doit contenir que des RESTRICTIONS au jeu de résultats. Si vous mélangez des critères de jointure de table avec des restrictions d'ensemble de résultats, vous (et d'autres) trouverez votre requête plus difficile à lire. Vous devez absolument utiliser JOINs et conserver la clause FROM une clause FROM et la clause WHERE une clause WHERE.
la source
La seconde est préférée car elle est beaucoup moins susceptible d'entraîner une jointure croisée accidentelle en oubliant de mettre dans la clause where. Une jointure sans clause on échouera à la vérification de la syntaxe, une jointure de style ancien sans clause where n'échouera pas, elle fera une jointure croisée.
De plus, lorsque vous devez ultérieurement effectuer une jointure gauche, il est utile pour la maintenance qu'ils soient tous dans la même structure. Et l'ancienne syntaxe est obsolète depuis 1992, il est grand temps d'arrêter de l'utiliser.
De plus, j'ai constaté que de nombreuses personnes qui utilisent exclusivement la première syntaxe ne comprennent pas vraiment les jointures et la compréhension des jointures est essentielle pour obtenir des résultats corrects lors de l'interrogation.
la source
Je pense qu'il y a de bonnes raisons sur cette page d'adopter la deuxième méthode - en utilisant des JOIN explicites. Le clinquant est cependant que lorsque les critères JOIN sont supprimés de la clause WHERE, il devient beaucoup plus facile de voir les critères de sélection restants dans la clause WHERE.
Dans les instructions SELECT vraiment complexes, il devient beaucoup plus facile pour un lecteur de comprendre ce qui se passe.
la source
La
SELECT * FROM table1, table2, ...
syntaxe est correcte pour quelques tables, mais elle devient de plus en plus exponentiellement ( pas nécessairement une déclaration mathématiquement précise ) à mesure que le nombre de tables augmente.La syntaxe JOIN est plus difficile à écrire (au début), mais elle rend explicite quels critères affectent quelles tables. Cela rend beaucoup plus difficile de faire une erreur.
De plus, si toutes les jointures sont INNER, les deux versions sont équivalentes. Cependant, au moment où vous avez une jointure EXTERNE n'importe où dans l'instruction, les choses deviennent beaucoup plus compliquées et il est pratiquement garanti que ce que vous écrivez ne demandera pas ce que vous pensez avoir écrit.
la source
Lorsque vous avez besoin d'une jointure externe, la deuxième syntaxe est pas toujours requise:
Oracle:
MSSQLServer (bien qu'il soit obsolète dans la version 2000) / Sybase:
Mais revenons à votre question. Je ne connais pas la réponse, mais elle est probablement liée au fait qu'une jointure est plus naturelle (syntaxiquement, au moins) que d'ajouter une expression à une clause where lorsque vous faites exactement cela: rejoindre .
la source
J'entends beaucoup de gens se plaindre que la première est trop difficile à comprendre et qu'elle n'est pas claire. Je ne vois pas de problème avec cela, mais après avoir eu cette discussion, j'utilise le second même sur INNER JOINS pour plus de clarté.
la source
Pour la base de données, ils finissent par être les mêmes. Pour vous, cependant, vous devrez utiliser cette deuxième syntaxe dans certaines situations. Pour éditer des requêtes qui finissent par devoir l'utiliser (découvrir que vous aviez besoin d'une jointure gauche là où vous aviez une jointure droite), et pour des raisons de cohérence, je ne modéliserais que sur la 2ème méthode. Cela facilitera la lecture des requêtes.
la source
Eh bien, les première et deuxième requêtes peuvent donner des résultats différents, car une jointure gauche inclut tous les enregistrements de la première table, même s'il n'y a pas d'enregistrements correspondants dans la bonne table.
la source