web-dev-qa-db-fra.com

Différence de condition de filtre - Où la clause et la condition de jointure

Question de filtre rapide et facile.

Quelle serait la différence de sortie, ou quel impact cela aurait-il de déplacer une condition de filtre d'une clause WHERE dans la condition Join.

Par exemple:

Select a1.Name, a2.State
from student a1
left join location a2 on a1.name_id = a2.name_id
where a1.name LIKE 'A%'
and a2.state = 'New York';

Pour ça:

Select a1.Name, a2.State
from student a1
left join location a2 on (a1.name_id = a2.name_id) and a2.state = 'New York'
where a1.name LIKE 'A%';

Merci a tous.

7
LargeMarge

1) montrera les noms des étudiants qui commencent par "A" et dont l'emplacement est New York.
2) affichera tous les noms d'étudiants commençant par "A", 'New York' si l'état étudiant est New York, ou nul dans les autres cas (il n'y a pas d'état correspondant, ou l'état étudiant n'est pas New York)

La différence entre (1) et (2) - (1) n'aura pas d'étudiants non new-yorkais.

8
a1ex07

réponse de @ a1ex07 est tout à fait correct. Cependant, fournissons une réponse un peu plus générale.

Lorsque vous avez un TableA a LEFT JOIN TableB b, alors vous devez faire attention à la façon dont vous utilisez les champs TableB dans votre clause WHERE.

Pour toutes les lignes de TableA où il n'y a pas de ligne correspondante dans TableB, tous les champs de TableB seront définis sur NULL.

Regardons votre exemple.

Nous supposerons que vous voulez que toutes les lignes de TableA (student) qui n'ont pas de ligne correspondante dans TableB (location), ou qui ont une ligne correspondante dans TableBb.Column1 (location.State) est égal à "New York".

  1. Si votre clause WHERE inclut une vérification sur un champ TableB qui ne permet pas une valeur NULL dans ce champ, toutes les lignes TableA sans une correspondance TableB ligne sera exclue.

    Exemple: WHERE b.State = 'New York' - TableA lignes sans ligne TableB correspondante aurait B.Column1 comme NULL. Depuis NULL = 'New York' n'est pas VRAI, aucune des lignes TableA (student) sans ligne TableB (location) correspondante ne répond aux critères de la WHERE.

    En fait, cela rend le LEFT JOIN une INNER JOIN.

  2. Si vous autorisez les valeurs de TableB à être NULL, vous devez faire attention à ne pas autoriser plus de valeurs que vous signifier.

    Si vous modifiez l'exemple de clause WHERE ci-dessus en:

    WHERE (b.State = 'New York' OR b.State IS NULL)
    

    Les lignes TableA sans ligne TableB correspondante seront toujours incluses. Cependant, TableA rangera avec une ligne TableB correspondante où Column1 est défini sur NULL (dans votre cas, student lignes avec une ligne location correspondante, où le location.State est NULL). Ce n'est peut-être pas l'intention.

  3. Pour concrétiser notre intention supposée, vous avez au moins deux options:

    • Tout d'abord, vous pouvez placer la restriction sur les lignes TableB dans la condition JOIN:

      FROM TableA a
             LEFT JOIN TableB b ON (a.name_id = b.name_id AND b.State = 'New York')
      

      Cela laisse passer toutes les lignes TableA (student) où il n'y a pas de ligne TableB (location) correspondante; là où se trouve une ligne TableB correspondante, les lignes correspondantes de TableA et TableB seront uniquement être inclus si b.State est "New York".

    • Deuxièmement, incluez votre vérification dans la clause WHERE, mais utilisez la colonne JOIN dans TableB pour autoriser les valeurs NULL:

      FROM TableA a
             LEFT JOIN TableB b ON (a.name_id = b.name_id)
      WHERE (b.State = 'New York' OR b.name_id IS NULL)
      

      Cela suppose que a.name_id ne peut pas être nulle. Ensuite, la seule façon b.name_id peut être NULL si aucune correspondance n'a été trouvée pour le JOIN dans TableB. Encore une fois, TableA lignes sans correspondance TableB sont incluses (car b.name_id sera toujours NULL pour ces lignes). Avec notre hypothèse, où TableA a une ligne TableB correspondante, b.name_id ne sera jamais nul, donc b.State doit être "New York" pour cette paire de lignes correspondante TableA et TableB à inclure.

8
RDFozz