Je me demandais s'il y avait une différence dans la façon dont SQL exécute ces instructions de jointure:
SELECT * FROM a,b WHERE a.ID = b.ID
SELECT * FROM a JOIN b ON a.ID = b.ID
SELECT * FROM a JOIN b USING(ID)
Y a-t-il une différence de performances? Ou différence algorithmique?
Ou s'agit-il simplement de sucre syntaxique?
Il n'y a aucune différence de performance.
Cependant, le premier style est ANSI-89 et se cassera les jambes dans certains magasins. Y compris le mien. Le deuxième style est ANSI-92 et est beaucoup plus clair.
Exemples:
Quel est le JOIN, quel est le filtre?
FROM T1,T2,T3....
WHERE T1.ID = T2.ID AND
T1.foo = 'bar' AND T2.fish = 42 AND
T1.ID = T3.ID
FROM T1
INNER JOIN T2 ON T1.ID = T2.ID
INNER JOIN T3 ON T1.ID = T3.ID
WHERE
T1.foo = 'bar' AND T2.fish = 42
Si vous avez des JOINTS EXTÉRIEURS (=*
, *=
) alors le 2ème style fonctionnera comme annoncé. Le premier ne le sera probablement pas et est également déconseillé dans SQL Server 2005+
Le style ANSI-92 est également plus difficile à bollix. Avec l'ancien style, vous pouvez facilement vous retrouver avec un produit cartésien (jointure croisée) si vous manquez une condition. Vous obtiendrez une erreur de syntaxe avec ANSI-92.
Edit: Quelques précisions supplémentaires
Ce n'est pas seulement la syntaxe : il s'agit d'avoir une requête sémantiquement correcte
Edit, déc.2011
SQL Server logique ordre de traitement des requêtes est FROM, ON, JOIN, WHERE ...
Donc, si vous mélangez "jointures internes WHERE implicites" et "jointures externes FROM explicites", vous n'obtiendrez probablement pas les résultats attendus car la requête est ambiguë ...
La différence est la lisibilité et la maintenabilité. SELECT * FROM a JOIN b ON a.ID = b.ID
exprime votre intention exacte, au même endroit.
Je ne dirai pas définitivement, car je ne suis pas passé sous le capot du dernier optimiseur de requête, mais je suis assez confiant que vous regardez une différence triviale dans les performances, le cas échéant.
Je méprise quand vous forcez une jointure en utilisant WHERE
. Cela ne me semble pas juste, un hack sale. La bonne jointure ANSI consiste à utiliser ON:
SELECT
p.Product,
o.Order
FROM
Product p
INNER JOIN
Order o
ON
o.OrderID = p.OrderID
Préférez utiliser ON
lors de la jointure et WHERE
pour filtrer les résultats. N'oubliez pas OERE est l'une des dernières choses que vous utiliserez en plus du regroupement et de l'ordre par où vous souhaitez filtrer vos résultats. Vous ne devez donc pas joindre vos tables en utilisant WHERE
car il est très difficile à lire.
SELECT
p.Product,
o.Order
FROM
Product p
INNER JOIN
Order o
ON
o.OrderID = p.OrderID
WHERE
o.Category = 'IT'
En fin de compte, vous (le développeur) pourriez ne pas être dans le futur, donc la lisibilité et la maintenabilité aideront l'âme verseuse qui doit prendre en charge votre code :).
Quand je vois des développeurs utiliser WHERE
pour joindre leurs tables, c'est généralement une indication qu'ils ne connaissent pas assez T-SQL. C'est mon opinion personnel.
Regarde ça
Ceci est un doublon de cette SO question: jointures SQL explicites vs implicites . En général, je pense que l'implicite (où version) est de mauvaise forme et pas aussi clair que l'explicite (sur la version). Je pense aussi que l'implicite est déprécié mais pas à 100% sur celui-là. Le plan d'exécution est le même pour les deux cependant.
Personne n'a encore fourni de réponse sur la syntaxe USING(...)
.
Bien que ces deux requêtes soient logiquement équivalentes, et également du point de vue de la plupart des optimiseurs modernes:
SELECT * FROM a, b WHERE a.id = b.id
SELECT * FROM a JOIN b ON a.id = b.id
Celui-ci a une sémantique légèrement différente:
SELECT * FROM a JOIN b USING (id)
En supposant le schéma suivant:
CREATE TABLE a (id int, a1 int, a2 int);
CREATE TABLE b (id int, b1 int, b2 int);
Les deux premières requêtes verront leurs astérisques étendus pour:
SELECT a.id, a.a1, a.a2, b.id, b.a1, b.a2 FROM ...
Alors que la troisième requête aura son astérisque étendu à:
SELECT coalesce(a.id, b.id) AS id, a.a1, a.a2, b.a1, b.a2 FROM ...
Ceci est très différent pour diverses raisons, notamment:
UNION
ou d'autres opérations d'ensemble. Ce que vous n'avez probablement pas, avec un astérisque.a.id
Ou b.id
, Seulement une colonne id
. Alors que PostgreSQL autorise toujours les références qualifiantes à id
(par exemple lorsque vous devez les lever sans ambiguïté), Oracle par exemple ne le permet pas.USING(...)
, la projection de a.*
Ou b.*
N'est plus possible dans Oracle.