Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

SQL:obtenha produtos de uma categoria, mas também deve estar em outro conjunto de categorias


Esse tipo de problema é chamado de divisão relacional .

Existem duas soluções comuns:

  1. A primeira solução agrupa as categorias correspondentes e compara com uma string fixa:
    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. A segunda solução faz um 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) 
    

Eu abordo essas soluções em minha apresentação Padrões de consulta SQL, otimizados . Descobri em meus testes que a solução de junção é muito melhor para o desempenho.

A sugestão do @Tom está certa, veja como isso ficaria em uma 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;

O DISTINCT que @Tom sugere não deve ser necessário, porque sua tabela p2c deve ter uma restrição UNIQUE (product_id, category_id).