3 votes

Recherche d'attributs multiples dans une requête MySQL (avec exemple de travail)

J'ai les tableaux suivants

table : produits

+------------+--------------------+
| product_id | name               |
+------------+--------------------+
| 1          | samsung galaxy s8  |
| 2          | apple iphone 7     |
+------------+--------------------+

table : attributs

+--------------+--------------------+
| attribute_id | name               |
+--------------+--------------------+
| 1            | brand              |
| 2            | color              |
+--------------+--------------------+

table : valeurs des attributs

+--------------------+--------------+------------+---------------------+
| attribute_value_id | attribute_id | product_id | value               |
+--------------------+--------------+------------+---------------------+
| 1                  | 1            | 1          | samsung             |
| 2                  | 2            | 1          | blue                |
| 3                  | 1            | 2          | apple               |
| 4                  | 2            | 2          | red                 |
+--------------------+--------------+------------+---------------------+

Et j'ai les requêtes suivantes :

Requête 1 (Fonctionne !)

    SELECT
                p.product_id                AS product_id,
                p.name                      AS product_name,
                v.value                     AS attribute_value,
                a.attribute_id              AS attribute_id,
                a.name                      AS attribute_name,
                c.name                      AS attributes_category_name
    FROM
                products p
    LEFT JOIN
                attribute_values v USING (product_id)
    LEFT JOIN
                attributes a USING (attribute_id)
    WHERE
                p.product_id IN (
                    SELECT 
                       p.product_id 
                    FROM 
                       products p 
                    LEFT JOIN 
                      attribute_values v USING (product_id) 
                    LEFT JOIN  
                      attributes a USING (attribute_id) 
                    WHERE  
                      (a.name = 'brand' AND (v.value = 'samsung'))
                )

Requête 2 (NE FONCTIONNE PAS !)

    SELECT
                p.product_id                AS product_id,
                p.name                      AS product_name,
                v.value                     AS attribute_value,
                a.attribute_id              AS attribute_id,
                a.name                      AS attribute_name,
                c.name                      AS attributes_category_name
    FROM
                products p
    LEFT JOIN
                attribute_values v USING (product_id)
    LEFT JOIN
                attributes a USING (attribute_id)
    WHERE
                p.product_id IN ( 
                    SELECT   
                      p.product_id  
                    FROM   
                      products p  
                    LEFT JOIN   
                      attribute_values v USING (product_id)  
                    LEFT JOIN   
                      attributes a USING (attribute_id)  
                    WHERE   
                      (a.name = 'brand' AND (v.value = 'samsung'))   
                      AND (a.name = 'color' AND (v.value = 'blue'))  
                   )

Comme vous pouvez le constater, la différence entre les 2 requêtes se situe au niveau de la clause WHERE.

Query 1:
--------
p.product_id IN (
    SELECT  
        p.product_id 
    FROM  
        products p 
    LEFT JOIN  
        attribute_values v USING (product_id) 
    LEFT JOIN  
        attributes a USING (attribute_id) 
    WHERE  
        (a.name = 'brand' AND (v.value = 'samsung')) 
   )

Query 2:
--------
p.product_id IN (
    SELECT 
        p.product_id 
    FROM  
        products p 
    LEFT JOIN  
        attribute_values v USING (product_id) 
    LEFT JOIN  
        attributes a USING (attribute_id) 
    WHERE  
        (a.name = 'brand' AND (v.value = 'samsung'))  
        AND (a.name = 'color' AND (v.value = 'blue')) 
   )

Je recherche dans la première requête uniquement la marque > samsung, dans la deuxième requête la marque > samsung AND couleur > bleu.

Quelqu'un sait-il pourquoi ma deuxième requête ne fonctionne pas ?

1voto

Keyur Panchal Points 1310

Regardez votre WHERE condition dans second requête :

 WHERE  
  (a.name = 'brand' AND (v.value = 'samsung'))  
  AND (a.name = 'color' AND (v.value = 'blue'))

Cette condition est finalement similaire à :

WHERE a.name = 'brand' AND v.value = 'samsung'
  AND a.name = 'color' AND v.value = 'blue'

Et cela va NEVER va être TRUE pour tout enregistrement.

1voto

karran Points 159

Je n'ai pas encore assez de réputation pour commenter sur stackoverflow, mais je pense que la table c n'est jamais déclarée, donc je la supprime. C'est le moyen que j'ai trouvé pour résoudre votre problème en utilisant votre code.

SELECT
          p.product_id                AS product_id,
          p.name                      AS product_name,
          v.value                     AS attribute_value,
          a.attribute_id              AS attribute_id,
          a.name                      AS attribute_name/*,
          c.name                      AS attributes_category_name*/
FROM
          products p
LEFT JOIN
          attribute_values v USING (product_id)
LEFT JOIN
          attributes a USING (attribute_id)
WHERE 
          p.product_id IN ( 
              SELECT   
                p2.product_id  
              FROM   
                products p2  
              LEFT JOIN   
                attribute_values v USING (product_id)  
              LEFT JOIN   
                attributes a USING (attribute_id)  
              WHERE   
                a.name = 'brand' AND v.value = 'samsung' and p2.product_id IN (
                  SELECT   
                    p3.product_id  
                  FROM   
                    products p3  
                  LEFT JOIN   
                    attribute_values v USING (product_id)  
                  LEFT JOIN   
                    attributes a USING (attribute_id)
                  WHERE a.name = 'color' AND v.value = 'blue'
              )
          )

donc en gros vous devez d'abord faire un filtre après l'autre, pas les deux en même temps, il n'y a pas d'attribut_value qui soit bleu et un samsung. J'espère que cela vous aidera

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X