Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Mysql - otimização - vários group_concat e junções usando ter


Reescreva a consulta para usar WHERE em vez de HAVING . Porque WHERE é aplicado quando o MySQL realiza pesquisa em linhas e pode usar index. HAVING é aplicado depois que as linhas são selecionadas para filtrar o resultado já selecionado. HAVING por design não pode usar índices.
Você pode fazer isso, por exemplo, desta forma:
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

Atualizar


Estamos juntando cada tabela duas vezes.
Primeiro para verificar se ela contém algum valor (condição de FIND_IN_SET ).
A segunda junção produzirá dados para GROUP_CONCAT para selecionar todos os valores do produto da tabela.

Atualização 2


Como @Matt Raines comentou, se não precisarmos listar valores de produtos com GROUP_CONCAT , a consulta fica ainda mais simples:
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

Isso selecionará todos os produtos com três atributos filtrados.