web-dev-qa-db-fra.com

Pourquoi LEFT JOIN de MySQL renvoie-t-il les enregistrements "NULL" avec la clause WHERE?

Aujourd'hui, j'ai essayé des requêtes MySQL plus complexes et j'ai remarqué que LEFT JOIN de MySQL ne fonctionnait pas avec la clause WHERE. Je veux dire, il renvoie certains enregistrements, mais pas ceux qui sont vides du côté droit.

Par exemple, disons que nous avons des tables:

des albums; albums_rap 
 id pistes du titre de l'artiste; id artiste titre rang 
 ---- -------- ---------- ---------------; ---- --------- ----- -------------- 
 1 John Doe Mix CD 20; 3 Marque CD n ° 7 15 
 2 Marque CD n ° 7 35;

Et quand j'exécute cette requête:

SELECT 
    t1.artist as artist,
    t1.title as title,
    t1.tracks as tracks,
    t2.rank as rank,
FROM
    albums as t1
LEFT JOIN
    albums_rap as t2
ON 
    t1.artist LIKE t2.artist
AND
    t1.title LIKE t2.title
WHERE
    t2.rank != 17

J'ai compris:

titre d'artiste titre rang 
 ------ ----- ------ ----- 
 Marque CD n ° 7 35 15

mais quand je remplace "WHERE" par "AND" dans cette requête, je reçois:

titre d'artiste titre rang 
 ------ --------- ------ ----- 
 Marque CD n ° 7 35 15 
 John Doe Mix CD 20 NULL

Pourquoi le premier ne renvoie pas d'enregistrements avec "NULL" (null n'est pas égal à 17 ...)

J'espère que vous avez compris ce que je voulais dire et vous m'expliquerez d'une manière ou d'une autre la différence. Désolé pour mon mauvais anglais, ce n'est pas ma langue maternelle.

8
simivar

Une condition de jointure gauche et un filtre de condition ne sont pas identiques. Les données sont filtrées par la clause where après la jointure physique. Si vous regardez une jointure gauche, toutes les lignes de votre table gauche seront renvoyées. Une fois que vous avez une clause where, le résultat de la jointure est filtré. Le résultat est donc similaire à une jointure interne. Vous voudrez vous concentrer sur les deux diagrammes du côté gauche de l'image ci-dessous.

enter image description here

29
akhila vangala

Premier cas:

Une fois joints, les enregistrements sont filtrés par la (clause WHERE). Donc, seulement 1 résultat.

Deuxième cas (lorsque vous remplacez WHERE par AND)

Renverra toutes les entrées de jointure + entrées satisfaites dans la deuxième condition (t2.rank! = 17). C’est pourquoi ici vous obtenez 2 enregistrements (un de jointure + un autre de clause AND)

2
Infra DBA

"Le mot clé LEFT JOIN renvoie toutes les lignes de la table de gauche (table1), avec les lignes correspondantes dans la table de droite (table2). Le résultat est NULL du côté droit en l'absence de correspondance ."

La citation ci-dessus est de w3schools.com

Cependant, lorsque vous placez une clause WHERE sur un LEFT JOIN, SQL le traite maintenant comme un INNER JOIN et:

"Le mot clé INNER JOIN sélectionne toutes les lignes des deux tables tant qu'il existe une correspondance entre les colonnes des deux tables."

Également cité de w3schools.com

TLDR;

L'introduction de la clause WHERE dans un LEFT OUTER JOIN confère à la jointure le comportement d'un INNER JOIN

0
David Zehr

La solution à cette question devient assez intuitive une fois que l’on connaît l’ordre d’exécution ou les phases de traitement de requêtes logiques de l’instruction SQL. La commande est: -

1. FROM
2. ON
3. OUTER
4. WHERE
5. GROUP BY
6. CUBE | ROLLUP
7. HAVING
8. SELECT
9. DISTINCT
10. ORDER BY
11. TOP

Comme ON est exécuté avant la partie OUTER (LEFT/RIGHT) (ajout de lignes de valeur NULL) de JOIN, le 1er cas contient des lignes avec des valeurs NULL dans la colonne de rang. Dans le 2e cas, les lignes sont filtrées en fonction sur les valeurs de la colonne de rang après l'exécution de OUTER JOIN (LEFT JOIN ici). Par conséquent, les lignes avec des valeurs NULL dans la colonne de classement sont filtrées.

Une chose très importante que vous pouvez remarquer dans votre requête SQL est la comparaison avec NULL Cette zone nécessite une attention particulière, car les valeurs NULL sont associées aux valeurs NULL/NON NULL à l'aide des opérateurs arithmétiques normaux. result NULL (ni les valeurs TRUE ni FALSE), car NULL signifie qu'aucune valeur n'est disponible pour la comparaison. Ce comportement est défini dans la norme ANSI SQL 92. (Ceci peut être annulé en désactivant le paramètre ansi null (le nom réel peut varier) dans certains processeurs SQL) Ainsi, votre requête SQL with clause clause filtre les lignes avec la valeur NULL dans la colonne rank qui peut sembler contre-intuitive en raison de "17! = NULL" semble TRUE ex-

NULL = NULL résultats NULL/UNKNOWN

17 = résultats NULL NULL/UNKNOWN

17! = NULL résultats NULL? INCONNU

Voici quelques articles/blogs intéressants à titre de référence:

http://blog.sqlauthority.com/2009/04/06/sql-server-logical-query-processing-phases-order-of-statement-execution/http://blog.sqlauthority.com/2009/03/15/sql-server-interesting-observation-of-on-clause-on-left-join-how-on-clause-effects-resultset-in-left-join/http://www.xaprb.com/blog/2006/05/18/why-null-never-compares-false-to-any-chose-in-sql/

0
Aditya Guru