Това е случай на релационно разделение:
SELECT c.id, c.name
FROM components_componentproperty cp1
JOIN components_componentproperty cp2 USING (component_id)
JOIN components_component c ON c.id = cp1.component_id
WHERE cp1.property_id = 9102 AND cp1.value IN ('4015', '4016')
AND cp2.property_id = 8801 AND cp2.value = '3'
AND c.type_id = 3832
GROUP BY c.id;
Тук сме събрали арсенал от подходящи техники:
Проверете за голям брой свойства
Можете да разширите горната заявка и за ръка, пълна с имоти, тя ще бъде сред най-бързите възможни решения. За по-голям брой ще бъде по-удобно (и ще започне да бъде по-бързо) да преминете по този маршрут:
Пример за 5 свойства, разгънете при необходимост:
SELECT c.id, c.name
FROM (
SELECT id
FROM (
SELECT component_id AS id, property_id -- alias id just to shorten syntax
FROM components_componentproperty
WHERE property_id IN (9102, 8801, 1234, 5678, 9876) -- expand as needed
GROUP BY 1,2
) cp1
GROUP BY 1
HAVING count(*) = 5 -- match IN expression
) cp2
JOIN components_component c USING (id);
Допълнителната стъпка на вътрешната подзаявка cp1
е необходимо само, защото очевидно имате множество записи на (component_id, property_id)
в components_componentproperty
. Ние можем сгънете cp1
и cp2
в едно и проверете
HAVING count(DISTINCT property_id) = 5
Но очаквам това да е по-скъпо, тъй като count(DISTINCT col)
изисква една операция за сортиране на ред .
За много дълги списъци IN
е лош избор. Помислете за следното: