Skriv om frågan för att använda WHERE
istället för HAVING
. Eftersom WHERE
tillämpas när MySQL utför sökning på rader och den kan använda index. HAVING
tillämpas efter att rader har valts för att filtrera redan valda resultat. HAVING
av design kan inte använda index.
Du kan till exempel göra det så här:
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
Uppdatera
Vi går med i varje bord två gånger.
Först för att kontrollera om det innehåller något värde (villkor från FIND_IN_SET
).
Second join kommer att producera data för GROUP_CONCAT
för att välja alla produktvärden från tabellen.
Uppdatering 2
Som @Matt Raines kommenterade, om vi inte behöver lista produktvärden med GROUP_CONCAT
, frågan blir ännu enklare:
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
Detta kommer att välja alla produkter med tre filtrerade attribut.