Detta är ett fall av relationell uppdelning:
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;
Vi har samlat en arsenal av relevanta tekniker här:
Se efter ett stort antal egenskaper
Du kan utöka ovanstående fråga och för en handfull fastigheter kommer det att vara bland de snabbaste möjliga lösningarna. För ett större nummer kommer det att vara bekvämare (och börjar också bli snabbare) att gå den här vägen:
Exempel för 5 fastigheter, utöka efter behov:
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);
Det extra steget i den inre underfrågan cp1
är bara nödvändigt eftersom du uppenbarligen har flera poster per (component_id, property_id)
i components_componentproperty
. Vi kunde vik cp1
och cp2
till en och kontrollera
HAVING count(DISTINCT property_id) = 5
Men jag förväntar mig att det blir dyrare, eftersom count(DISTINCT col)
behöver en sorteringsoperation per rad .
För mycket långa listor IN
är ett dåligt val. Tänk på: