Este es un caso de división relacional:
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;
Hemos reunido un arsenal de técnicas relevantes aquí:
Buscar un gran número de propiedades
Puede expandir la consulta anterior y, para un puñado de propiedades, estará entre las soluciones más rápidas posibles. Para un número mayor será más conveniente (y también empezará a ser más rápido) seguir esta ruta:
Ejemplo para 5 propiedades, expanda según sea necesario:
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);
El paso adicional de la subconsulta interna cp1
solo es necesario, porque obviamente tiene varias entradas por (component_id, property_id)
en components_componentproperty
. Nosotros podríamos doblar cp1
y cp2
en uno y comprobar
HAVING count(DISTINCT property_id) = 5
Pero espero que sea más caro, ya que count(DISTINCT col)
necesita una operación de clasificación por fila .
Para listas muy largas IN
es una mala elección. Considere: