WHERE
を使用するようにクエリを書き直します HAVING
の代わりに 。 WHERE
MySQLが行の検索を実行し、インデックスを使用できる場合に適用されます。 HAVING
行が選択された後に適用され、すでに選択された結果をフィルタリングします。 HAVING
設計上、インデックスを使用することはできません。
たとえば、次のように使用できます。
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
更新
各テーブルを2回結合しています。
最初に、テーブルに値が含まれているかどうかを確認します(FIND_IN_SET
からの条件) )。
2回目の結合により、GROUP_CONCAT
のデータが生成されます テーブルからすべての製品値を選択します。
アップデート2
@Matt Rainesがコメントしたように、GROUP_CONCAT
で商品の値を一覧表示する必要がない場合 、クエリがさらに簡単になります:
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
これにより、3つのフィルタリングされた属性を持つすべての製品が選択されます。