2009-05-18 19 views
9

Si je lance la requête SQL suivantecommande SQL des opérations

SELECT * 
FROM A 
LEFT JOIN B 
ON A.foo=B.foo 
WHERE A.date = "Yesterday" 

L'énoncé WHERE s'évalué avant ou après la JOIN?

Si après, quelle serait une meilleure façon d'écrire cette instruction afin que retourne uniquement les lignes A de "Yesterday" sont jointes à B?

+0

'ce serait une meilleure façon d'écrire cette déclaration afin que seules les lignes A de "Yesterday" sont jointes à B. »(réponse tardive) ->' INNER JOIN' –

Répondre

8

Cela dépend de la base de données. Sur SQL Server, exécutez: SET SHOWPLAN_ALL ON puis exécutez la requête, vous obtiendrez une idée de ce qui se passe lors de son exécution.

1

Dépend des index et des statistiques.

Vous devez afficher le chemin d'exécution de la requête pour déterminer où (le cas échéant) les optimisations doivent être appliquées. Sémantiquement: après le JOIN.

5

Mais dans ce cas, il n'y a pas de différence dans le timing, car il est sur le côté gauche de la JOIN.

Comme vous l'avez déjà, "seules les lignes dans A de" Hier "sont jointes à B".

L'optimiseur est libre de réorganiser son ordre de fonctionnement en fonction des équivalences dans l'algèbre relationnelle.

Ce ne retourne A.date = "Yesterday" et B où il rejoint peut trouver un match sur foo:

SELECT * FROM A 
LEFT JOIN B 
    ON A.foo=B.foo 
WHERE A.date="Yesterday" 

Cela renvoie tous les A quels que soient les critères et B où A.date joint = » Hier "ET il trouve un match sur foo:

SELECT * FROM A 
LEFT JOIN B 
    ON A.foo=B.foo 
    AND A.date="Yesterday" 
+0

Juste pour comprendre, dites-vous que mettre les critères dans la clause WHERE est mieux du point de vue des performances que de les placer dans la clause JOIN? – NotMe

+0

Cela ne fait aucune différence pour les performances sur un INNER JOIN et c'est pourquoi l'optimiseur a plus d'options pour déplacer les choses sur INNER JOINs. Sur un OUTER JOIN (LEFT ou RIGHT), cela affecte la sémantique de la déclaration, donc la performance n'est généralement pas le problème. –

7

Votre idée de" évaluation "n'est pas correcte car SQL est un langage déclaratif.

Vous pouvez voir le plan d'exécution de la requête. Dans MySQL préfixez votre requête avec le mot-clé describe pour voir le plan d'exécution.

2

L'ordre des opérations pour satisfaire une requête est déterminé pourquoi le caprice de l'optimiseur de requête de la base de données particulière. Un optimiseur de requête essaie de produire un bon "plan de requête" (ensemble d'opérations) basé sur ce qu'il peut glaner de la requête et sur les statistiques de la base de données (qui pourraient inclure la cardinalité des tables et certaines distributions de données) .

Dans votre cas, la réponse peut dépendre si vous avez un index secondaire sur A.date

d'optimisation des requêtes un sujet assez riche. La documentation pour la base de données que vous utilisez aura beaucoup plus à dire à ce sujet.

1

dans SQL Server:

En règle générale, les clauses JOIN sont évaluées avant les clauses WHERE.

En cas de jointures complexes que les filtres ont besoin dans la jointure, je les écris avec mon rejoindre

SELECT * 
FROM A 
LEFT JOIN B 
    ON A.Foo1 = B.Foo1 
    And A.Date = 'Yesterday' 
OUTER JOIN C 
    ON B.Foo2 = C.Foo2 
JOIN D 
    ON B.Foo3 = D.Foo3 
+0

Cela n'a pas la même signification lorsque vous l'utilisez dans LEFT JOIN. Dans LEFT JOIN, lorsque les critères ne sont pas satisfaits, les lignes LEFT sont toujours renvoyées, et toutes les colonnes de la droite sont NULL. –

+0

Je suis corrigé sur l'exemple fourni. J'essayais de mettre l'accent sur la partie d'une clause avec la jointure appropriée. J'ai corrigé la déclaration. –

+0

:) je suis recorrected .. je ne peux pas corriger la déclaration. –

0
SELECT * 
FROM (SELECT * FROM A WHERE Date = 'Yesterday') A 
LEFT JOIN B 
    ON A.Foo1 = B.Foo1 
OUTER JOIN C 
    ON B.Foo2 = C.Foo2 
JOIN D 
    ON B.Foo3 = D.Foo3