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: