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ż: