Mysql
 sql >> Database >  >> RDS >> Mysql

SQL:ottieni prodotti da una categoria ma deve anche trovarsi in un altro insieme di categorie

Questo tipo di problema è chiamato divisione relazionale .

Esistono due soluzioni comuni:

  1. La prima soluzione mette insieme le categorie corrispondenti e le confronta con una stringa fissa:

    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 seconda soluzione esegue un JOIN per ogni valore richiesto:

    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) 
    

Tratterò queste soluzioni nella mia presentazione Modelli di query SQL ottimizzati . Nei miei test ho scoperto che la soluzione di join è molto migliore in termini di prestazioni.

Il suggerimento di @Tom è giusto, ecco come sarebbe in una query 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;

Il DISTINCT che @Tom suggerisce non dovrebbe essere necessario, perché la tua tabella p2c dovrebbe avere un vincolo UNICO su (id_prodotto, ID_categoria).