web-dev-qa-db-fra.com

SQL JOIN: existe-t-il une différence entre USING, ON ou WHERE?

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?

43
Yochai Timmer

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

  • La raison de ne pas utiliser "join the where" (implicite) est les résultats douteux avec les jointures externes.
  • Si vous utilisez des JOINTS EXTÉRIEURS explicites + des JOINTS INTÉRIEURS implicites, vous obtiendrez toujours des résultats douteux + vous aurez des incohérences dans l'utilisation

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ë ...

53
gbn

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.

4
Pete M

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.

2
JonH
0
Jason

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.

0
scrappedcola

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:

  • Le nombre de colonnes projetées est désormais de 5 au lieu de 6. Cela pourrait gêner lorsque vous utilisez UNION ou d'autres opérations d'ensemble. Ce que vous n'avez probablement pas, avec un astérisque.
  • Il n'y a plus de colonne qualifiée (et dupliquée) 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.
  • Par conséquent, dans la troisième requête avec la syntaxe USING(...), la projection de a.* Ou b.* N'est plus possible dans Oracle.
0
Lukas Eder