Riscrivi la query per utilizzare WHERE
invece di HAVING
. Perché WHERE
viene applicato quando MySQL esegue la ricerca su righe e può utilizzare index. HAVING
viene applicato dopo che le righe sono state selezionate per filtrare il risultato già selezionato. HAVING
by design non può utilizzare gli indici.
Puoi farlo, ad esempio, in questo modo:
SELECT p.id, p.name, p.default_image_id,
GROUP_CONCAT( DISTINCT pc.colour_id ) AS product_colours,
GROUP_CONCAT( DISTINCT pt.tag_id ) AS product_tags,
GROUP_CONCAT( DISTINCT ps.tag_id ) AS product_sizes
FROM shop_products p
JOIN shop_product_to_colours pc_test ON p.id = pc_test.product_id AND pc_test.colour_id = 18
JOIN shop_products_to_tag pt_test ON p.id = pt_test.product_id AND pt_test.tag_id = 1
JOIN shop_product_colour_to_sizes ps_test ON p.id = ps_test.product_id AND ps_test.tag_id = 17
JOIN shop_product_to_colours pc ON p.id = pc.product_id
JOIN shop_products_to_tag pt ON p.id = pt.product_id
JOIN shop_product_colour_to_sizes ps ON p.id = ps.product_id
WHERE p.category_id = '50'
GROUP BY p.id
ORDER BY p.name ASC
Aggiorna
Uniamo ogni tabella due volte.
Prima per verificare se contiene un valore (condizione da FIND_IN_SET
).
Il secondo join produrrà dati per GROUP_CONCAT
per selezionare tutti i valori dei prodotti dalla tabella.
Aggiornamento 2
Come ha commentato @Matt Raines, se non abbiamo bisogno elenca i valori dei prodotti con GROUP_CONCAT
, la query diventa ancora più semplice:
SELECT p.id, p.name, p.default_image_id
FROM shop_products p
JOIN shop_product_to_colours pc ON p.id = pc.product_id
JOIN shop_products_to_tag pt ON p.id = pt.product_id
JOIN shop_product_colour_to_sizes ps ON p.id = ps.product_id
WHERE p.category_id = '50'
AND (pc.colour_id = 18 AND pt.tag_id = 1 AND ps.tag_id = 17)
GROUP BY p.id
ORDER BY p.name ASC
Questo selezionerà tutti i prodotti con tre attributi filtrati.