sql >> Base de Datos >  >> RDS >> Mysql

SQL:obtenga productos de una categoría, pero también debe estar en otro conjunto de categorías

Este tipo de problema se llama división relacional .

Hay dos soluciones comunes:

  1. La primera solución une las categorías coincidentes y las compara con una cadena fija:

    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 segunda solución hace un JOIN para cada valor requerido:

    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) 
    

Cubro estas soluciones en mi presentación Patrones de consultas SQL optimizados . Descubrí en mis pruebas que la solución de unión es mucho mejor para el rendimiento.

La sugerencia de @Tom es correcta, así es como se vería en una consulta completa:

    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;

El DISTINCT que @Tom sugiere que no debería ser necesario, porque su tabla p2c debería tener una restricción ÚNICA sobre (id_producto, id_categoría).