Вы можете использовать оператор not exists
для поиска клиентов, у которых нет движений ie с топ-5 актерами (чтобы определить, какие из их прокатов являются фильмами с этими актерами, вы можете использовать оператор in
):
select c.costumer_id, c.first_name, c.last_name
from costumers c
where not exists (
select *
from rental r
inner join inventory i on i.inventory_id = r.inventory_id
inner join film f on f.film_id = i.film_id
inner join film_actor fa on fa.film_id = f.film_id and
fa.actor_id in (<< Here_goes_your_top_5_actors_query >>)
where r.costumer_id = c.costumer_id
)
Это самый прямой и простой для понимания перевод ваших логи c в SQL, но коррелированный подзапрос может привести к очень плохой производительности (особенно, когда большое количество записей участвует). Если этот запрос слишком медленный для вас, вы можете выбрать несколько прокатов, сгруппированных по потребителям, и суммировать их фильмы с одним из этих актеров, возвращая только клиентов с суммой ноль.
Внутренняя теперь соединения должны быть заменены на левые, потому что нас интересуют строки, в которых нет ни одного объекта film_actors, соответствующего 5 лучшим актерам, поэтому внутреннее объединение не возвращает этих клиентов.
select c.costumer_id, c.first_name, c.last_name
from costumer c
left join rental r on r.costumer_id = c.costumer_id
left join inventory i on i.inventory_id = r.inventory_id
left join film_actor fa on fa.film_id = i.film_id and
fa.actor_id in (<< Here_goes_your_top_5_actors_query >>)
group by c.costumer_id, c.first_name, c.last_name
having sum(fa.film_id) = 0
PS: в этом более быстром запросе я удалил объединение с фильмами, потому что оно никогда не было необходимым, мы не используем никаких данных из таблицы фильмов, поэтому мы можем напрямую присоединить инвентарь к film_actor.