Viết lại truy vấn để sử dụng WHERE
thay vì HAVING
. Bởi vì WHERE
được áp dụng khi MySQL thực hiện tìm kiếm trên các hàng và nó có thể sử dụng chỉ mục. HAVING
được áp dụng sau khi các hàng được chọn để lọc kết quả đã chọn. HAVING
theo thiết kế không thể sử dụng chỉ mục.
Ví dụ:bạn có thể làm điều đó theo cách này:
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
Cập nhật
Chúng tôi sẽ nối mỗi bảng hai lần.
Trước tiên, hãy kiểm tra xem nó có chứa giá trị nào không (điều kiện từ FIND_IN_SET
).
Tham gia thứ hai sẽ tạo ra dữ liệu cho GROUP_CONCAT
để chọn tất cả các giá trị sản phẩm từ bảng.
Cập nhật 2
Như @Matt Raines đã nhận xét, nếu chúng ta không cần liệt kê các giá trị sản phẩm bằng GROUP_CONCAT
, truy vấn trở nên đơn giản hơn nữa:
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
Thao tác này sẽ chọn tất cả các sản phẩm có ba thuộc tính đã lọc.