PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Recuperar várias linhas com consulta usando AND e OR


Este é um caso de divisão 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;

Reunimos aqui um arsenal de técnicas relevantes:

Verifique se há um grande número de propriedades


Você pode expandir a consulta acima e, para uma mão cheia de propriedades, estará entre as soluções mais rápidas possíveis. Para um número maior será mais conveniente (e também começando a ser mais rápido) seguir este caminho:

Exemplo para 5 propriedades, expanda conforme necessário:
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);

A etapa extra da subconsulta interna cp1 só é necessário, porque você obviamente tem várias entradas por (component_id, property_id) em components_componentproperty . Nós poderíamos dobrar cp1 e cp2 em um e verifique
HAVING count(DISTINCT property_id) = 5

Mas espero que seja mais caro, pois count(DISTINCT col) precisa de uma operação de classificação por linha .

Para listas muito longas IN é uma má escolha. Considerar: