Omskriv forespørgslen for at bruge WHERE
i stedet for HAVING
. Fordi WHERE
anvendes, når MySQL udfører søgning på rækker, og det kan bruge indeks. HAVING
anvendes, efter at rækker er valgt for at filtrere det allerede valgte resultat. HAVING
by design kan ikke bruge indekser.
Du kan f.eks. gøre det på denne måde:
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
Opdater
Vi slutter os til hver tabel to gange.
Først for at kontrollere, om den indeholder en eller anden værdi (betingelse fra FIND_IN_SET
).
Second join vil producere data for GROUP_CONCAT
for at vælge alle produktværdier fra tabellen.
Opdatering 2
Som @Matt Raines kommenterede, hvis vi ikke har brug for liste over produktværdier med GROUP_CONCAT
, forespørgslen bliver endnu enklere:
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
Dette vil vælge alle produkter med tre filtrerede attributter.