sql >> Base de Datos >  >> RDS >> Mysql

Mysql - optimización - múltiples group_concat y uniones usando tener

Reescriba la consulta para usar WHERE en lugar de HAVING . Porque WHERE se aplica cuando MySQL realiza una búsqueda en filas y puede usar index. HAVING se aplica después de seleccionar las filas para filtrar el resultado ya seleccionado. HAVING por diseño no puede usar índices.
Puede hacerlo, por ejemplo, de esta manera:

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

Actualizar

Estamos uniendo cada tabla dos veces.
Primero para verificar si contiene algún valor (condición de FIND_IN_SET ).
La segunda unión producirá datos para GROUP_CONCAT para seleccionar todos los valores de productos de la tabla.

Actualización 2

Como comentó @Matt Raines, si no necesitamos enumerar los valores del producto con GROUP_CONCAT , la consulta se vuelve aún más simple:

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

Esto seleccionará todos los productos con tres atributos filtrados.