Quelle est la différence entre mettre un WHERE dans un ON ou en-dehors, au sein de jointures ?

Le problème exposé dans ce sujet a été résolu.

Hello !

On m’a dit que les requêtes suivantes ne sont pas équivalentes :

SELECT table_feature_value.id_feature_value FROM feature_value as table_feature_value

LEFT JOIN feature_product as table_feature_product ON table_feature_product.id_feature = table_feature_value.id_feature

LEFT JOIN product as table_product ON table_product.id_product = table_feature_product.id_product


WHERE ( table_feature_product.id_feature IS NULL OR table_product.id_product IS NULL )

et

SELECT fv.id_feature_value
FROM feature_value fv
LEFT JOIN feature_product fp
    ON fp.id_feature = fv.id_feature AND fp.id_feature IS NULL
LEFT JOIN product p
    ON p.id_product = fp.id_product AND p.id_product IS NULL
;

L’idée étant de récupérer les id_feature_value qui soit ne sont associées à aucun product, soit sont associées à des product mais aucun n’existe actuellement en base.

J’comprends pas déjà le principe de mettre le contenu qui devrait appartenir à un WHERE dans un ON d’une jointure… Déjà ça c’est wtf pour moi, mais ensuite que je n’obtienne pas les mêmes résultats ça me sidère.

Merci d’avance !

Salut,

Soit j’ai pas les yeux en face des trous, soit le premier script a un OR sur le fait que certains id sont NULL alors que le second équivaut à avoir un AND

J’comprends pas déjà le principe de mettre le contenu qui devrait appartenir à un WHERE dans un ON d’une jointure…

Pas compris, les deux peuvent prendre une condition, où est le problème ?

+2 -0

Je réécris la 1ère requete, avec les mêmes alias que dans la 2, pour que ce soit plus visuel.

SELECT table_feature_value.id_feature_value FROM feature_value as fv
LEFT JOIN feature_product as fp ON fp.id_feature = fv.id_feature
LEFT JOIN product as p ON p.id_product = fp.id_product
WHERE ( fp.id_feature IS NULL OR p.id_product IS NULL )

Dans la 2ème requete, les lignes qui ont un 'élément' dans fp sont éliminées. Ca ne correspond pas à ton besoin. Ta 2ème requete élimine trop de ligne à cause du filtre fp.id_feature is null.

Regarde étape par étape cette 2ème requête :

SELECT fv.id_feature_value
FROM feature_value fv
LEFT JOIN feature_product fp
    ON fp.id_feature = fv.id_feature AND fp.id_feature IS NULL

On prend les lignes de fv qui n’ont pas d’équivalent dans fp.

Et ensuite sur ce périmètre, on fait une autre jointure … on a déjà éliminé certaines lignes qu’on voulait garder.

Je pense que la 1ère requête peut même se réécrire :

SELECT table_feature_value.id_feature_value FROM feature_value as fv
LEFT JOIN feature_product as fp ON fp.id_feature = fv.id_feature
LEFT JOIN product as p ON p.id_product = fp.id_product
WHERE  p.id_product IS NULL 

Si fp.id_feature est NULL, alors nécessairement, p.id_product sera null aussi.

Je pense que la 1ère requête peut même se réécrire :

SELECT table_feature_value.id_feature_value FROM feature_value as fv
LEFT JOIN feature_product as fp ON fp.id_feature = fv.id_feature
LEFT JOIN product as p ON p.id_product = fp.id_product
WHERE  p.id_product IS NULL 

Si fp.id_feature est NULL, alors nécessairement, p.id_product sera null aussi.

elegance

Quelque chose m’échappe peut-être mais cette requête ne m’a pas l’air correcte. Si p.id_product IS NULL alors le JOIN avec feature_product ne retournera jamais rien donc on peut le supprimer coomplètement de la requête.

C’est un left join, et pas un join.

On a 3 tables A B C : A est en relation avec B et B est en relation avec C

Avec un join simple, on aurait les 'enregistrements complets’, ceux pour lesquels A B et C sont associés.

Avec un left join entre A et B et un left join entre B et C, on a toutes les lignes de A, avec en face, les données associées venant de B, et en face, les données associées venant de C.

Avec un left join et cette clause P.id_product is null, on dit : je veux les lignes de A, avec en face les informations venant de B, mais ce qu’on veut, c’est exclure les lignes 'complètes’, celles où A, B et C sont reliées.

Oui, je connais la différence entre un normal join et un left join.

Mais à quoi bon faire le join si tu sais que la colonne que tu utilises pour faire ton join est nulle ? Quelle est la différence entre ta requête et

SELECT fv.id_feature_value FROM feature_value as fv
LEFT JOIN feature_product as fp ON fp.id_feature = fv.id_feature
WHERE  fp.id_product IS NULL 

Dans tous les cas, avec ou sans left join, aucun record ne sera supprimé

+0 -0

C’est un left join, et pas un join.

On a 3 tables A B C : A est en relation avec B et B est en relation avec C

Avec un join simple, on aurait les 'enregistrements complets’, ceux pour lesquels A B et C sont associés.

Avec un left join entre A et B et un left join entre B et C, on a toutes les lignes de A, avec en face, les données associées venant de B, et en face, les données associées venant de C.

Avec un left join et cette clause P.id_product is null, on dit : je veux les lignes de A, avec en face les informations venant de B, mais ce qu’on veut, c’est exclure les lignes 'complètes’, celles où A, B et C sont reliées.

elegance

J’ai eu du mal à comprendre ton msg, mais avec un left join, on est d’accord qu’on a les colonnes de toutes les tables impliquées même si la clef étrangère n’est pas trouvée ? Donc des null en pagaille, d’où mon is null sur la clef d’ailleurs.

nan ?

alors qu’un join normal impliquerait pas de valeur null sur les clefs étrangères uniquement.

+0 -0

On va réécrire tout ça, avec une logique totalement différente, sans aucun left join. Peut-être que ce sera plus clair.

La toute première requête peut se réécrire :


SELECT id_feature_value 
FROM feature_value 
where id_feature_value not in ( 
  SELECT fv.id_feature_value 
  FROM feature_value as fv
  JOIN feature_product as fp ON fp.id_feature = fv.id_feature
  JOIN product as p ON p.id_product = fp.id_product
  )

A l’intérieur des parenthèse, on a une sous-requête avec des joins normaux : liste des fv qui sont en relation avec un fp et un p.

Et on dit : je veux les éléments de fv qui ne sont pas dans cette sous requête. (les gran

La dernière requête que tu proposes (Migwel) peut se réécrire :

SELECT id_feature_value 
FROM feature_value 
where id_feature_value not in ( 
  SELECT fv.id_feature_value 
  FROM feature_value as fv
  JOIN feature_product as fp ON fp.id_feature = fv.id_feature
  )
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte