Dette er et tilfælde af relationel opdeling:
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 samlet et arsenal af relevante teknikker her:
Se efter et stort antal ejendomme
Du kan udvide ovenstående forespørgsel, og for en håndfuld ejendomme vil det være blandt de hurtigst mulige løsninger. For et større nummer vil det være mere bekvemt (og også begynde at være hurtigere) at gå denne rute:
Eksempel på 5 ejendomme, udvid 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 ekstra trin i den indre underforespørgsel cp1
er kun nødvendigt, fordi du åbenbart har flere poster pr. (component_id, property_id)
i components_componentproperty
. Vi kunne fold cp1
og cp2
i en og tjek
HAVING count(DISTINCT property_id) = 5
Men jeg forventer, at det bliver dyrere, da count(DISTINCT col)
kræver en sorteringsoperation pr. række .
For meget lange lister IN
er et dårligt valg. Overvej: