PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Rufen Sie mehrere Zeilen mit einer Abfrage mit AND und OR ab

Dies ist ein Fall von relationaler Division:

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;

Wir haben hier ein Arsenal relevanter Techniken zusammengestellt:

Suchen Sie nach einer großen Anzahl von Eigenschaften

Sie können die obige Abfrage erweitern und für eine Handvoll Eigenschaften wird sie zu den schnellstmöglichen Lösungen gehören. Für eine größere Anzahl ist es bequemer (und auch langsamer), diesen Weg zu gehen:

Beispiel für 5 Eigenschaften, nach Bedarf erweitern:

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

Der zusätzliche Schritt der inneren Unterabfrage cp1 ist nur notwendig, da Sie offensichtlich mehrere Einträge pro (component_id, property_id) haben in components_componentproperty . Wir könnten falte cp1 und cp2 in eins und überprüfen

HAVING count(DISTINCT property_id) = 5

Aber ich erwarte, dass das teurer wird, da count(DISTINCT col) benötigt eine Sortieroperation pro Zeile .

Für sehr lange Listen IN ist eine schlechte Wahl. Bedenken Sie: