Mysql
 sql >> Base de données >  >> RDS >> Mysql

SQL :obtenir des produits à partir d'une catégorie, mais doit également figurer dans un autre ensemble de catégories

Ce type de problème est appelé division relationnelle .

Il existe deux solutions courantes :

  1. La première solution regroupe les catégories correspondantes et les compare à une chaîne fixe :

    SELECT p2c.product_id
    FROM oc_product_to_category p2c
    GROUP BY p2c.product_id
    HAVING GROUP_CONCAT(p2c.category_id SEPARATOR ',' ORDER BY p2c.category_id) = '1,2'
    
  2. La deuxième solution fait un JOIN pour chaque valeur requise :

    SELECT p.product_id 
    FROM oc_product p 
    INNER JOIN oc_product_to_category p2c1 
      ON (p.product_id = p2c1.product_id AND p2c1.category_id = 1) 
    INNER JOIN oc_product_to_category p2c2 
      ON (p.product_id = p2c2.product_id AND p2c2.category_id = 2) 
    

Je couvre ces solutions dans ma présentation SQL Query Patterns, Optimized . J'ai trouvé dans mes tests que la solution de jointure est bien meilleure pour les performances.

La suggestion de @Tom est juste, voici à quoi cela ressemblerait dans une requête complète :

    SELECT p.product_id, GROUP_CONCAT(p2c3.category_id SEPARATOR ',') AS categories
    FROM oc_product p 
    INNER JOIN oc_product_to_category p2c1 
      ON (p.product_id = p2c1.product_id AND p2c1.category_id = 1) 
    INNER JOIN oc_product_to_category p2c2 
      ON (p.product_id = p2c2.product_id AND p2c2.category_id = 2) 
    INNER JOIN oc_product_to_category p2c3
      ON (p.product_id = p2c3.product_id)
    GROUP BY p.product_id;

Le DISTINCT que @Tom suggère ne devrait pas être nécessaire, car votre table p2c devrait avoir une contrainte UNIQUE sur (product_id, category_id).