42 votes

Y at-il quelque chose de mal avec les jointures qui n'utilisent pas le mot clé JOIN dans SQL ou MySQL?

Quand j'ai commencé à écrire des requêtes de base de données je ne connaissais pas le mot clé de JOINTURE encore et, naturellement, je vient de prolonger ce que je savais déjà et a écrit des requêtes comme ceci:

SELECT a.someRow, b.someRow 
FROM tableA AS a, tableB AS b 
WHERE a.ID=b.ID AND b.ID= $someVar

Maintenant que je sais que c'est la même chose qu'un INNER JOIN-je trouver toutes ces requêtes dans mon code et de me demander si je devrais réécrire. Est-il quelque chose de puant sur eux ou sont-ils bien?


EDIT:

Ma réponse résumé: Il n'y a rien de mal avec cette requête, MAIS en utilisant les mots clés ne sera probablement rendre le code plus lisible et maintenable.

Ma conclusion: je ne vais pas changer mon vieux interrogations, mais je vais corriger mon style d'écriture et d'utiliser les mots clés dans le futur.

MERCI pour vos réponses!

36voto

Daniel Spiewak Points 30706

Le filtrage se joint uniquement à l'aide d' WHERE peut être extrêmement inefficace dans certains scénarios courants. Par exemple:

SELECT * FROM people p, companies c 
    WHERE p.companyID = c.id AND p.firstName = 'Daniel'

La plupart des bases de données exécuter cette requête tout à fait littéralement, prendre d'abord le produit Cartésien de l' people et companies tables et puis le filtrage par ceux qui ont de correspondance companyID et id champs. Alors que la contrainte de produit n'existe pas partout, mais dans la mémoire et ensuite seulement pour un instant, son calcul ne prendra un certain temps.

Une meilleure approche consiste à regrouper les contraintes de l' JOINs, le cas échéant. Ce n'est pas seulement subjectivement plus facile à lire, mais aussi beaucoup plus efficace. Ainsi:

SELECT * FROM people p JOIN companies c ON p.companyID = c.id
    WHERE p.firstName = 'Daniel'

C'est un peu plus long, mais la base de données est capable de regarder l' ON de la clause et les utiliser pour calculer la contrainte JOIN directement, plutôt que de commencer avec tout et puis limitant. C'est plus rapide à calculer (surtout avec les grands ensembles de données et/ou de nombreuses jointures de table) et nécessite moins de mémoire.

Je change chaque requête, je vois qui utilise la "virgule JOIN" de la syntaxe. À mon avis, le seul but de son existence est la concision. Considérant l'impact sur les performances, je ne pense pas que c'est une raison impérieuse.

10voto

Les INNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL OUTER JOIN plus verbeux sont issus de la syntaxe ANSI SQL / 92 pour la jointure. Pour moi, cette verbosité rend la jointure plus claire pour le développeur / DBA de l'intention de la jointure.

6voto

Meff Points 4347

Dans SQL Server, il existe toujours des plans de requête à vérifier, une sortie texte peut être réalisée comme suit:

 SET SHOWPLAN_ALL ON
GO

DECLARE @TABLE_A TABLE
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    Data VARCHAR(10) NOT NULL
)
INSERT INTO @TABLE_A
SELECT 'ABC' UNION 
SELECT 'DEF' UNION
SELECT 'GHI' UNION
SELECT 'JKL' 

DECLARE @TABLE_B TABLE
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    Data VARCHAR(10) NOT NULL
)
INSERT INTO @TABLE_B
SELECT 'ABC' UNION 
SELECT 'DEF' UNION
SELECT 'GHI' UNION
SELECT 'JKL' 

SELECT A.Data, B.Data
FROM
    @TABLE_A AS A, @TABLE_B AS B
WHERE
    A.ID = B.ID

SELECT A.Data, B.Data
FROM
    @TABLE_A AS A
    INNER JOIN @TABLE_B AS B ON A.ID = B.ID
 

Maintenant, je vais omettre le plan pour la variable de table crée, le plan pour les deux requêtes est identique, cependant:

  SELECT A.Data, B.Data  FROM   @TABLE_A AS A, @TABLE_B AS B  WHERE   A.ID = B.ID
  |--Nested Loops(Inner Join, OUTER REFERENCES:([A].[ID]))
       |--Clustered Index Scan(OBJECT:(@TABLE_A AS [A]))
       |--Clustered Index Seek(OBJECT:(@TABLE_B AS [B]), SEEK:([B].[ID]=@TABLE_A.[ID] as [A].[ID]) ORDERED FORWARD)
 SELECT A.Data, B.Data  FROM   @TABLE_A AS A   INNER JOIN @TABLE_B AS B ON A.ID = B.ID
  |--Nested Loops(Inner Join, OUTER REFERENCES:([A].[ID]))
       |--Clustered Index Scan(OBJECT:(@TABLE_A AS [A]))
       |--Clustered Index Seek(OBJECT:(@TABLE_B AS [B]), SEEK:([B].[ID]=@TABLE_A.[ID] as [A].[ID]) ORDERED FORWARD)
 

Donc, réponse courte - Pas besoin de réécrire, à moins que vous passiez beaucoup de temps à essayer de les lire chaque fois que vous les maintenez?

5voto

Powerlord Points 43989

C'est plus un choix de syntaxe. Je préfère regrouper mes conditions de jointure avec mes jointures et j'utilise donc la syntaxe INNER JOIN

 SELECT a.someRow, b.someRow
FROM tableA AS a
INNER JOIN tableB AS b
  ON a.ID = b.ID
WHERE b.ID = ?
 

(? être un espace réservé)

4voto

ilitirit Points 4636

En général:

Utilisez le mot-clé JOIN pour lier (c.-à-d. "Rejoindre") des clés primaires et des clés étrangères.

Utilisez la clause WHERE pour limiter votre jeu de résultats aux enregistrements qui vous intéressent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X