Ако вашият дизайн налага референтна цялост, не е нужно да се присъединявате към таблицата residences
изобщо за тази цел. Също така приемайки UNIQUE
или PK
ограничение за (residence_id, amenity_id)
(в противен случай имате нужда от различни заявки!)
Най-добрата заявка зависи от това какво точно имате .
Използвайки функция за прозорец, вие можете дори направете това в едно ниво на заявка:
SELECT count(*) OVER () AS ct
FROM listed_amenities
WHERE amenity_id IN (48, 49, 50)
GROUP BY residence_id
HAVING count(*) = 3
LIMIT 1;
Тази прозоречна функция добавя общия брой към всеки ред, без да агрегира редове. Разгледайте последователността от събития в SELECT
заявка:
Съответно можете да използвате подобна заявка, за да върнете всички квалифицирани идентификатори (или дори цели редове) и да добавите броя към всеки ред (излишно):
SELECT residence_id, count(*) OVER () AS ct
FROM listed_amenities
WHERE amenity_id IN (48, 49, 50)
GROUP BY residence_id
HAVING count(*) = 3;
Но по-добре използвайте подзаявка, това обикновено е много по-евтино :
SELECT count(*) AS ct
FROM (
SELECT 1
FROM listed_amenities
WHERE amenity_id IN (48, 49, 50)
GROUP BY residence_id
HAVING count(*) = 3
) sub;
Вие можете връща масив от идентификатори (за разлика от set по-горе) в същото време, срещу почти никакви разходи:
SELECT array_agg(residence_id ) AS ids, count(*) AS ct
FROM (
SELECT residence_id
FROM listed_amenities
WHERE amenity_id IN (48, 49, 50)
GROUP BY residence_id
HAVING count(*) = 3
) sub;
Има много други варианти, ще трябва да изясните очаквания резултат. Като този:
SELECT count(*) AS ct
FROM listed_amenities l1
JOIN listed_amenities l2 USING (residence_id)
JOIN listed_amenities l3 USING (residence_id)
WHERE l1.amenity_id = 48
AND l2.amenity_id = 49
AND l2.amenity_id = 50;
По принцип това е случай на релационно разделение. Тук сме събрали арсенал от техники: