PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Récupérer plusieurs lignes avec une requête en utilisant AND et OR

C'est un cas de division relationnelle :

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;

Nous avons rassemblé ici un arsenal de techniques pertinentes :

Recherchez un grand nombre de propriétés

Vous pouvez développer la requête ci-dessus et pour une poignée de propriétés, ce sera parmi les solutions les plus rapides possibles. Pour un plus grand nombre, il sera plus pratique (et commence également à être plus rapide) d'emprunter cette route :

Exemple pour 5 propriétés, développez si nécessaire :

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);

L'étape supplémentaire de la sous-requête interne cp1 est seulement nécessaire, car vous avez évidemment plusieurs entrées par (component_id, property_id) dans components_componentproperty . Nous pourrions plier cp1 et cp2 en un et vérifiez

HAVING count(DISTINCT property_id) = 5

Mais je m'attends à ce que ce soit plus cher, car count(DISTINCT col) nécessite une opération de tri par ligne .

Pour les très longues listes IN est un mauvais choix. Considérez :