Přepište dotaz tak, aby používal WHERE
místo HAVING
. Protože WHERE
se používá, když MySQL provádí vyhledávání v řádcích a může používat index. HAVING
se použije po výběru řádků k filtrování již vybraného výsledku. HAVING
by design nemůže používat indexy.
Můžete to udělat například takto:
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
Aktualizovat
Každou tabulku spojujeme dvakrát.
Nejprve zkontrolujte, zda obsahuje nějakou hodnotu (podmínka z FIND_IN_SET
).
Druhé připojení vytvoří data pro GROUP_CONCAT
pro výběr všech hodnot produktu z tabulky.
Aktualizace 2
Jak poznamenal @Matt Raines, pokud nepotřebujeme uvést hodnoty produktů pomocí GROUP_CONCAT
, dotaz se ještě zjednoduší:
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
Tím vyberete všechny produkty se třemi filtrovanými atributy.