Как переписать несколько левых объединений со многими условиями в Учении - PullRequest
0 голосов
/ 10 мая 2019

Я не хочу, чтобы вы тратили много времени на этот вопрос. Однако я чувствую, что допустил большую ошибку и что-то упустил при создании этого запроса. Похоже:

SELECT attributes, attributes_associations, COUNT(DISTINCT(products.id)) as count, attribute_groups, group_modifiers, linked_groups, linked_group_modifiers, attribute_linked_groups, attribute_category 
FROM App\Component\Attribute\Entity\Attribute attributes 
LEFT JOIN attributes.associations attributes_associations 
INNER JOIN attributes.products products 
LEFT JOIN attributes.group attribute_groups 
LEFT JOIN attribute_groups.modifiers group_modifiers 
LEFT JOIN attribute_groups.reverseLinkedGroups linked_groups 
LEFT JOIN linked_groups.modifiers linked_group_modifiers 
LEFT JOIN attributes.linkedGroups attribute_linked_groups 
LEFT JOIN attribute_groups.attributeConditions attribute_groupsattribute_conditions 
LEFT JOIN linked_groups.attributeConditions linked_groupsattribute_conditions 
LEFT JOIN attribute_groups.groupConditions group_conditions 
LEFT JOIN group_conditions.attributes group_conditions_attributes 
LEFT JOIN group_conditions.linkedGroup group_linked_group_conditions 
LEFT JOIN group_linked_group_conditions.attributes group_linked_group_conditions_attributes 
LEFT JOIN linked_groups.groupConditions linked_group_conditions 
LEFT JOIN linked_group_conditions.attributes linked_group_conditions_attributes 
LEFT JOIN linked_group_conditions.linkedGroup reverse_linked_group_conditions 
LEFT JOIN reverse_linked_group_conditions.attributes reverse_linked_group_conditions_attributes 
LEFT JOIN attribute_groups.category attribute_category 
LEFT JOIN attribute_linked_groups.category attribute_linked_category 
LEFT JOIN linked_groups.category linked_category 
WHERE attributes.isVisible = :attributeIsVisible AND products.isVisible = :productIsVisible 
AND products.price > :priceMin AND products.price < :priceMax 
AND (
    (
        (attribute_groupsattribute_conditions.id IN(:attributes) AND attribute_groups.conditionType = :conditionAnd) 
        OR ((attribute_groupsattribute_conditions.id IN(SELECT attribute_groupsattribute FROM App\Component\Attribute\Entity\Attribute attribute_groupsattribute 
        WHERE attribute_groupsattribute.id = :attribute_groups0 OR attribute_groupsattribute.id = :attribute_groups1 OR attribute_groupsattribute.id = :attribute_groups2 OR attribute_groupsattribute.id = :attribute_groups3 OR attribute_groupsattribute.id = :attribute_groups4 OR attribute_groupsattribute.id = :attribute_groups5)) 
AND attribute_groups.conditionType = :conditionOr)) 
OR attribute_groupsattribute_conditions IS NULL) 
AND (((linked_groupsattribute_conditions.id IN(:attributes) 
AND linked_groups.conditionType = :conditionAnd) 
OR ((linked_groupsattribute_conditions.id IN(SELECT linked_groupsattribute 
FROM App\Component\Attribute\Entity\Attribute linked_groupsattribute 
WHERE linked_groupsattribute.id = :linked_groups0 
OR linked_groupsattribute.id = :linked_groups1 
OR linked_groupsattribute.id = :linked_groups2 
OR linked_groupsattribute.id = :linked_groups3 
OR linked_groupsattribute.id = :linked_groups4 
OR linked_groupsattribute.id = :linked_groups5)) 
AND linked_groups.conditionType = :conditionOr)) OR linked_groupsattribute_conditions IS NULL) 
AND (group_conditions_attributes.id IN(:attributes) OR group_conditions_attributes IS NULL) 
AND (group_linked_group_conditions_attributes.id IN(:attributes) OR group_linked_group_conditions_attributes IS NULL) 
AND (linked_group_conditions_attributes.id IN(:attributes) OR linked_group_conditions_attributes IS NULL) 
AND (reverse_linked_group_conditions_attributes.id IN(:attributes) OR reverse_linked_group_conditions_attributes IS NULL) 
AND (attribute_category.id = :attributeCategory OR attribute_linked_category.id = :attributeCategory OR linked_category.id = :attributeCategory) 
AND (products.id IN(SELECT p40 FROM App\Component\Product\Entity\Product p40 INNER JOIN p40.attributes filters40 WHERE filters40 = 341 OR attribute_groups.id = :group40)) 
AND (products.id IN(SELECT p44 FROM App\Component\Product\Entity\Product p44 INNER JOIN p44.attributes filters44 WHERE filters44 = 374 OR attribute_groups.id = :group44)) 
AND (products.id IN(SELECT p76 FROM App\Component\Product\Entity\Product p76 INNER JOIN p76.attributes filters76 WHERE filters76 = 950 OR attribute_groups.id = :group76)) 
AND (products.id IN(SELECT p77 FROM App\Component\Product\Entity\Product p77 INNER JOIN p77.attributes filters77 WHERE filters77 = 952 OR attribute_groups.id = :group77)) 
AND products.id IN(SELECT product_department FROM App\Component\Product\Entity\Product product_department INNER JOIN product_department.attributes filters1002  WHERE filters1002.id = :filter1002)
GROUP BY attributes.id, attributes_associations.id, attribute_groups.id, group_modifiers.id, linked_groups.id, linked_group_modifiers.id, attribute_linked_groups.id, attribute_groupsattribute_conditions.id, linked_groupsattribute_conditions.id 
ORDER BY count DESC, attributes.name ASC

Это фильтрующий запрос по атрибутам продукта, группам атрибутов и категориям атрибутов. Мне не удалось упростить этот запрос без потери его важной части. Основная проблема в том, что для выполнения этого запроса требуется 60 секунд. Ну, у меня меньше ста строк. Я не могу ожидать, что запрос выполняется около 2 минут.

Мне нужна Doctrine для поддержки левых соединений, чтобы при использовании $attribute->getGroup() новые запросы не производились. Кроме того, я не могу избежать левых объединений в некоторых случаях, потому что в таблицах объединения есть условия.

Я нашел эту статью https://www.colinodell.com/blog/201703/limiting-subqueries-doctrine-2-dql. Но это работает, только если выбрать только одну строку в подзапросе соединения. Более того, Doctrine не будет использовать результат подзапроса как правильные отношения сущностей.

Если я пропустил некоторые детали, дайте мне знать.

...