Les requêtes SQL suivantes sont les mêmes:
SELECT column1, column2
FROM table1, table2
WHERE table1.id = table2.id;
SELECT column1, column2
FROM table1 JOIN table2
ON table1.id = table2.id;
Et aboutissez certainement aux mêmes plans de requête sur chaque SGBD que j'ai jamais essayé.
Mais de temps en temps, je lis ou entends un avis selon lequel l’un est définitivement meilleur que l’autre. Naturellement, ces affirmations ne sont jamais étayées par une explication.
Là où je travaille, la deuxième version semble être favorisée par la majorité des autres développeurs, et je suis donc aussi orientée vers ce style pour minimiser les surprises. Mais dans mon cœur, je pense vraiment au premier (puisque c'est comme ça que je l'ai appris à l'origine).
L'une de ces formes est-elle objectivement meilleure que l'autre? Si non, quelles seraient les raisons pour utiliser l'un sur l'autre?
sql
coding-style
SingleNegationElimination
la source
la source
Réponses:
Je trouve que la deuxième forme est meilleure. C'est peut-être parce que c'est comme ça que je l'ai appris, je l'avoue, mais j'ai une raison concrète: la séparation des préoccupations. Mettre les champs que vous utilisez pour joindre les tables dans la clause where peut poser des problèmes de compréhension des requêtes.
Par exemple, prenons la requête suivante:
La requête ci-dessus a des conditions de jonction de table et des conditions de logique métier réelles combinées dans un seul espace. Avec une requête volumineuse, cela peut être très difficile à comprendre.
Cependant, prenons maintenant ce code:
Dans ce cas, tout ce qui concerne les tables ou leur relation est isolé de la clause from, tandis que la logique métier réelle pour la restriction de requête est contenue dans la clause where. Je pense que cela est beaucoup plus compréhensible, en particulier pour les requêtes plus importantes.
la source
La syntaxe de jointure a remplacé l'ancienne syntaxe de virgule en 1992. Il n'y a actuellement aucune raison de jamais écrire du code avec la syntaxe de virgule. Vous ne gagnez rien et vous êtes soumis à certains problèmes que vous n'avez tout simplement pas avec la syntaxe explicite.
En premier lieu, il est très facile de faire une jointure croisée accidentelle en omettant une condition où. C'est quelque chose que la syntaxe de jointure explicite peut empêcher, car vous obtiendrez une erreur de syntaxe.
Si vous envisagez une jointure croisée, la syntaxe de jointure explicite le précisera. Dans la syntaxe implicite, une personne effectuant la maintenance peut supposer que vous avez oublié d'ajouter la clause where.
Il y a ensuite le problème des jointures gauche et droite qui sont problématiques dans au moins quelques dbs utilisant la syntaxe implicite. Ils sont obsolètes dans SQL Server et ne renvoient en réalité pas des résultats corrects, même dans les versions antérieures. Aucune requête nécessitant une jointure externe ne doit contenir la syntaxe implicite dans SQL Server.
De plus, j'ai vu des questions ici et sur d'autres sites où des résultats erronés se produisaient lorsque les utilisateurs mélangeaient les jointures implicites et explicites (lors de l'ajout d'une jointure gauche, par exemple). Il est donc peu judicieux de les mélanger.
Enfin, de nombreuses personnes utilisant des jointures implicites ne comprennent pas réellement les jointures. Ceci est une compréhension critique que vous devez avoir pour interroger efficacement une base de données.
la source
Ha. Je viens de trouver une réponse possible à ma propre question en consultant la documentation de PostgreSQL . Pour résumer ce que cette page explique, la requête résultante est toujours la même, mais le nombre de plans que l'optimiseur doit prendre en compte augmente de manière exponentielle avec le nombre de jointures.
Après environ six de ces jointures, le nombre est si important que le temps nécessaire pour planifier la requête peut être perceptible. Après environ dix, l'optimiseur passera d'une recherche exhaustive des plans à une recherche probabiliste et risque de ne pas arriver au plan optimal. .
En définissant un paramètre d'exécution, vous pouvez demander au planificateur de traiter les jointures internes et croisées explicitement mentionnées différemment des jointures implicites, en les forçant à se placer en haut du plan et à ne pas explorer d'autres options.
Il est à noter que le comportement par défaut est le même dans les deux cas et que pour obtenir des plans alternatifs, il est nécessaire de connaître les composants internes des dbms et les particularités des tables en question pour obtenir un résultat différent.
la source
Eh bien voici la théorie de la théorie des ensembles:
Lorsque vous utilisez une virgule pour séparer deux (ou plus) noms de table, vous souhaitez obtenir le produit cartésien. Chaque ligne de la table "de gauche" sera "concaténée" avec celle de la table de droite.
Maintenant, si vous écrivez quelque chose dans la clause where, c'est comme si vous mettiez une condition sur cette "concaténation" en indiquant quelles lignes "concaténer" avec quelles lignes.
Il s’agit en fait de "joindre" les lignes :) et, par conséquent, le mot-clé join qui aide à fournir une syntaxe plus lisible et qui est plus compréhensible que vous "vouliez" vraiment rejoindre certaines valeurs communes. Semblable à ce que @Dustin a clarifié ci-dessus.
Désormais, chaque SGBD est intelligent, c’est-à-dire qu’il ne calcule pas d’abord le produit cartésien puis ne filtre pas les données (ce qui génère un gaspillage extrême), mais le fait plutôt en fonction de la structure de la requête. La seule chose à laquelle je peux penser, c’est que, lorsque vous lui demandez de «rejoindre», c’est comme rendre explicite l’activité de création de lien et vous aide probablement à exécuter le code plus rapidement (de combien? Vous devrez le profiler et voir), mais virgule séparée, il faut un peu de temps pour «déterminer» la stratégie optimale. Je me trompe peut-être, mais je ne fais que supposer de manière éclairée comment coder cela ...
la source
Je pense qu'il est généralement préférable d'utiliser les instructions JOIN pour ce cas.
Si, à l’avenir, il se produit une situation nécessitant le remplacement de la déclaration d’une déclaration INNER JOIN par une déclaration OUTER JOIN, il sera beaucoup plus facile à faire avec la deuxième instruction.
la source
Tous les SGBDR vont les rendre identiques en termes d’exécution. Cela revient à savoir si l’on est plus lisible et plus expressif.
Utilisez la commande JOIN pour indiquer clairement ce qui correspond à la jointure et à la sélection réelle, comme dans:
contre.
Ce dernier cas indique immédiatement quelle est la condition de jointure et quel est le critère de sélection.
la source
Je n’ai jamais vu les deux résultats dans un ensemble différent d’optimisations et, si la mémoire est mémorisée, c’était dans ms-sql2k lors d’une requête très complexe. Dans cet exemple, l'ancien formulaire utilisé avec * = entraînait des performances 4x plus rapides. Personne, y compris nos techniciens de Microsoft, ne pourrait jamais expliquer pourquoi. Les gars de MS ont qualifié cela d’erreur. Je ne l'ai jamais revu.
Étant donné que la plupart des SGBDR sont suffisamment intelligents pour ne pas traiter tous les cartésiens, la principale raison pour laquelle je peux penser à ne pas l'utiliser (à part qu'il est amorti) est que la plupart des personnes de moins de 30-35 avec lesquelles j'ai travaillé n'ont jamais vu le forme ancienne avant et se perdre terriblement quand ils le rencontrent.
la source
L'ancien style est obsolète, vous ne devriez pas l'utiliser.
Il ne devrait même pas y avoir de discussion sur la question de savoir si l’on est meilleur ou non. Le nouveau code ne devrait pas utiliser l'ancienne syntaxe.
la source
Une des raisons de la syntaxe plus concise est qu’elle est plus concise, elle est donc plus facile à lire. Je pense que le cas commenté ressemble à l’écriture arithmétique en COBOL, par exemple MULTIPLI A BY B DONNANT C.
la source