web-dev-qa-db-fra.com

MySQL sélectionnez rejoindre où ET où

J'ai deux tables dans ma base de données:

Produits

  • id (int, clé primaire)
  • nom (varchar)

ProductTags

  • product_id (entier)
  • tag_id (entier)

Je souhaite sélectionner des produits ayant toutes les balises données. J'ai essayé:

SELECT
    *
FROM
    Products
JOIN ProductTags ON Products.id = ProductTags.product_id
WHERE
    ProductTags.tag_id IN (1, 2, 3)
GROUP BY
    Products.id

Mais cela me donne des produits ayant l'une des étiquettes données, au lieu d'avoir toutes les étiquettes données. L'écriture WHERE tag_id = 1 AND tag_id = 2 est inutile, car aucune ligne ne sera renvoyée.

13
Darrarski

Ce type de problème est connu sous le nom de division relationnelle

SELECT Products.* 
FROM Products
JOIN ProductTags ON Products.id = ProductTags.product_id
WHERE ProductTags.tag_id IN (1,2,3)
GROUP BY Products.id /*<--This is OK in MySQL other RDBMSs 
                          would want the whole SELECT list*/

HAVING COUNT(DISTINCT ProductTags.tag_id) = 3 /*Assuming that there is a unique
                                              constraint on product_id,tag_id you 
                                              don't need the DISTINCT*/
20
Martin Smith

vous devez avoir un groupe par/compter pour vous assurer que tous sont pris en compte

select Products.*
  from Products 
         join ( SELECT Product_ID
                  FROM ProductTags
                  where ProductTags.tag_id IN (1,2,3)
                  GROUP BY Products.id
                  having count( distinct tag_id ) = 3 ) PreQuery
        on ON Products.id = PreQuery.product_id 
0
DRapp

MySQL WHERE fieldname IN (1,2,3) est essentiellement un raccourci pour WHERE fieldname = 1 OR fieldname = 2 OR fieldname = 3. Donc, si vous n'obtenez pas la fonctionnalité souhaitée avec WHERE ... IN puis essayez de passer à ORs. Si cela ne vous donne toujours pas les résultats souhaités, alors peut-être WHERE ... IN n'est pas la fonction que vous devez utiliser.

0
WNRosenberg