To jest przypadek podziału relacyjnego:
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;
Zebraliśmy tutaj arsenał odpowiednich technik:
Sprawdź dużą liczbę nieruchomości
Możesz rozwinąć powyższe zapytanie i dla garści nieruchomości będzie to jedno z najszybszych możliwych rozwiązań. W przypadku większej liczby wygodniej (a także szybciej) będzie jechać tą trasą:
Przykład dla 5 właściwości, rozwiń w razie potrzeby:
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);
Dodatkowy krok wewnętrznego podzapytania cp1 jest konieczne, ponieważ oczywiście masz wiele wpisów na (component_id, property_id) w components_componentproperty . moglibyśmy złóż cp1 i cp2 w jeden i sprawdź
HAVING count(DISTINCT property_id) = 5
Ale spodziewam się, że będzie drożej, ponieważ count(DISTINCT col) wymaga jednej operacji sortowania na wiersz .
W przypadku bardzo długich list IN to zły wybór. Rozważ: