Req SQL avec LEFT JOIN : Afficher tous les produits, y compris ceux qui ne sont pas dans table pivot (Many to Many)

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

Bonjour.

J’ai besoin d’aide SVP, pour une req SQL que je n’arrive pas à finir.

Je souhaite lister tous mes produits, et dans ce listage je souhaite afficher son stock pour le magasin actif (magasin actif = magasin sur lequel est loggé l’User).

J’ai 3 tables :

shops : contient tous les magasins (pour le moment, il y en a 2).

products : contient tous les produits.

product__shop : c’est la table pivot pour faire la relation Many to Many entre les magasins et les produits. Et dans cette table pivot j’ai bien sûr 2 colonnes pour les 2 clés étrangères, et j’ai aussi une colonne quantity_in_stock qui me sert à indiquer la quantité en stock de chaque produit pour chaque magasin.

Voici ma req SQL (dans cette exemple, je veux afficher tous mes produits + afficher leur stock WHERE le magasin actif qui a l’ID 1) :

SELECT `products`.*,
       `product__shop`.`quantity_in_stock`
FROM `products`
LEFT JOIN `product__shop`
    ON `products`.`id` = `product__shop`.`product_id`
WHERE `product__shop`.`shop_id` = 1

Cette req SQL m’affiche bien tous les produits qui ont leur stock renseigné dans la table pivot product__shop.

Mais dans mon application web, parfois des produits peuvent ne pas avoir leur stock renseigné dans cette table pivot (donc pas de ligne pour ce produit WHERE ce magasin). Et le problème, c’est que lorsqu’un produit n’a pas son stock renseigné dans la table pivot, le produit n’apparaît pas dans mon listage… Or je souhaite afficher tous les produits (de ma table products) y compris ce qui ne sont pas dans la table pivot product__shop WHERE se magasin actif.

Comment puis-je faire ceci SVP ?

Car avec ma req SQL actuelle, c’est normal que j’ai ce comportement, le WHERE product__shop.shop_id = 1 "transforme" mon LEFT JOIN en INNER JOIN, mais il doit bien y avoir une solution pour avoir le résultat que je souhaite ?

Merci d’avance.

+0 -0

Tu peux tout à fait mettre des contraintes supplémentaires dans le ON de la clause JOIN.

SpaceFox

Oui, j’avais essayé, mais sans succès (j’avais surement du mal m’y prendre). Tu penses qu’il faut que j’ajoute quoi contraintes supplémentaire dans le ON du JOIN ? Merci.

+0 -0

Bonjour, en mettant simplement la condition du where dans le on ça ne marche pas ?

SELECT `products`.*,
       `product__shop`.`quantity_in_stock`
FROM `products`
LEFT JOIN `product__shop`
    ON `products`.`id` = `product__shop`.`product_id`
    AND `product__shop`.`shop_id` = 1

Merci à tous pour vos réponses.

Bonjour, en mettant simplement la condition du where dans le on ça ne marche pas ?

SELECT `products`.*,
       `product__shop`.`quantity_in_stock`
FROM `products`
LEFT JOIN `product__shop`
    ON `products`.`id` = `product__shop`.`product_id`
    AND `product__shop`.`shop_id` = 1

Thallo

Effectivement, ça m’affiche bien toutes mes lignes de produits. Mais il y a maintenant un autre problème. C’est que ça ne m’affiche plus la quantité en stock des produits dans le listage. Et quand (dans la vue du listage des produits) je fait un :

var_dump( $product->quantity_in_stock );

ça me retourne NULL. Comment ça se fait ?

Merci.

+0 -0

Salut,

Une jointure left implique que si la correspondance n’existe pas pour la table de droite, les données relatives à cette table (pour la ligne en question) seront à null. C’est normal que tu ais null dans ton cas.

C’est donc juste un cas particulier à gérer :

SELECT `products`.*,
       IF (`product__shop`.`quantity_in_stock` IS NULL, 0, `product__shop`.`quantity_in_stock`) as `real_quantity_in_stock`
FROM `products`
LEFT JOIN `product__shop`
    ON `products`.`id` = `product__shop`.`product_id`
    AND `product__shop`.`shop_id` = 1

J’ai fait ça de tête sans tester, faudra peut-être paufiner

Salut,

Une jointure left implique que si la correspondance n’existe pas pour la table de droite, les données relatives à cette table (pour la ligne en question) seront à null. C’est normal que tu ais null dans ton cas.

Merci pour ta réponse. Mais dans mon cas, ça me met NULL pour toutes mes lignes (y compris pour les produits qui ont une correspondance dans la table pivot).

Ton code (le IF) ne change rien, à part que ça m’affiche 0 sur toutes mes lignes au lieu de NULL.

Pour les produits qui on une correspondance dans la table pivot (qui ont leur quantité en stock renseignée dans la colonne 'quantity_in_stock' de la table pivot), faudrait que ça m’affiche la valeur au lieu de NULL ou de 0.

+0 -0

Tu m’as mis le doute un instant, donc j’ai fait une requête similaire avec ma propre base et tout se passe bien, l’équivalent de la table produit affiche bien les données et pas null.

Ton code (le IF) ne change rien, à part que ça m’affiche 0 sur toutes mes lignes au lieu de NULL.

Oui c’est le but, si tu n’as pas de lien entre products et shop, tu n’as donc pas de stocks, donc 0 est la valeur attendue.

A moins que quelqu’un comprenne mieux ta problématique, tu peux éventuellement créer un jeu de données de test et nous les fournir.

Tu m’as mis le doute un instant, donc j’ai fait une requête similaire avec ma propre base et tout se passe bien, l’équivalent de la table produit affiche bien les données et pas null.

Ton code (le IF) ne change rien, à part que ça m’affiche 0 sur toutes mes lignes au lieu de NULL.

Oui c’est le but, si tu n’as pas de lien entre products et shop, tu n’as donc pas de stocks, donc 0 est la valeur attendue.

A moins que quelqu’un comprenne mieux ta problématique, tu peux éventuellement créer un jeu de données de test et nous les fournir.

obedient

Mince !

Le problème ne venait pas de ta req SQL, mais de mon ORM qui me générer ceci :

on `products`.`product_category_id` = 'products_categories.id'

au lieu de me générer ceci :

on `products`.`product_category_id` = `products_categories`.`id`

Problème résolu.

J’aurai appris un truc aujourd’hui.

Merci beaucoup à toi et aux autres qui m’ont répondus.

+0 -0
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