2014-10-30 3 views
0

Я работаю над заданием, которое требует от меня перечислять актеров и актрис, которые появляются в кино, а затем актеры и актрисы, которые снялись вместе с ними в других фильмах. Диаграмма базы данных можно просмотреть здесь: http://i.imgur.com/kj8qVgF.pngSQL - список атрибутов, появившихся вместе с другими

У меня есть запрос для первой части (получение имен актеров и актрис, которые появляются в определенном фильме).

SELECT DISTINCT n.name 
FROM cast_info c 
INNER JOIN name n 
ON (n.id = c.person_id) 
INNER JOIN title t 
ON (c.movie_id = t.id) 
CROSS JOIN role_type r 
WHERE (t.title = 'The Movie') AND (r.role = 'actress' OR r.role = 'actor') 

Могу ли я получить помощь, чтобы помочь мне найти актрис и актеров, которые играют с ними в других фильмах?

Пример:

Actors in a given movie 'The Movie': Bob, Joe, Billy 
Actors in a different movie 'Another Movie': Joe, Daniel, Frank 
Actors in another different movie 'Third Movie': Billy, Susan, Theodore 

Он должен вернуться Даниэль, Франк, Сьюзен, и Феодора, потому что они снимались по крайней мере один фильм с одним из актеров в данном фильме.

+0

Почему вы используете cross join для role_type? Почему бы не использовать внутреннее соединение row_type на c.role_id = r.id? –

+0

Вы должны опубликовать некоторые выборочные данные и ожидаемый результат, чтобы уточнить свой вопрос. –

+0

Я отправил это @JaugarChang –

ответ

1

В соответствии с вашим примером, и ваша модель - 3NF, поэтому вы можете использовать тривиальный IN для решения проблемы, как описано на естественном языке.

SELECT DISTINCT n.name 
FROM cast_info c 
INNER JOIN name n 
ON (n.id = c.person_id) 
INNER JOIN title t 
ON (c.movie_id = t.id) 
INNER JOIN role_type r 
ON (c.role_id = r.id) 
WHERE (r.role = 'actress' OR r.role = 'actor') -- find the actresses and actors ... 
AND c.movie_id IN   -- starred in at least one movie ... 
    (SELECT movie_id 
    FROM cast_info 
    WHERE id in   -- with one of the actors in the given movie => Bob, Joe, Billy 
     (SELECT cc.id 
     FROM cast_info cc 
     INNER JOIN role_type rr 
     ON (cc.role_id = rr.id) 
     WHERE (rr.role = 'actor') -- only select actors in the given movie 
     AND cc.movie_id in (select id from title where title = 'The Movie') 
     ) 
    ) 
AND c.id NOT IN -- except the actors in the given movie 
     (SELECT cc.id 
     FROM cast_info cc 
     INNER JOIN role_type rr 
     ON (cc.role_id = rr.id) 
     WHERE (rr.role = 'actor') -- only select actors in the given movie 
     AND cc.movie_id in (select id from title where title = 'The Movie') 
     ) 

Это легко перевести Естественный язык SQL, но не эффективным использованием IN, вы можете передать IN с EXISTS, что было бы более эффективным.

+0

Спасибо за ваш ответ! Я последовал этому, и это, казалось, сработало. Однако, в последних двух подзапросах, разве это не проверка для актеров и актрис?Когда я реализовал его для поиска как актеров, так и актрис в этих последних двух предложениях WHERE, я, казалось, не получил никаких результатов. –

+0

В вашем примере вам нужен Боб, Джо, Билли, чтобы получить от данного фильма, и вы сказали «с одним из актеров в данном фильме», поэтому я использую 'rr.role = 'actor''. Если вы хотите «актрисы и актеры», вы можете использовать 'rr.role in ('actress', 'actor')', не использовать '(r.role = 'actress' AND r.role = 'actor')' , в Энглисте другое, говорит «актеры и актрисы», и результатов не получится. –

1

Итак, мы снова встретимся. Надеюсь, у меня будет такая же помощь, как и ваш последний вопрос. Мне нравится, что вы начали, разбив это на более мелкие части. Я бы начал с того же места, что и вы, - заставляя всех актеров в нужный фильм. Я немного изменил ваш запрос, выбрав идентификатор лиц вместо имени, чтобы сохранить этот ответ немного короче и чище.

SELECT c.person_id 
FROM cast_info c 
JOIN title t ON c.movie_id = t.id 
JOIN role_type r ON c.role_id = r.id 
WHERE t.title = 'The Movie' AND (r.role = 'actress' OR r.role = 'actor'); 

* Обратите внимание, что я не использовал отчетливый здесь потому, что человек не должен появляться в этом фильме в качестве актера или актрисы более чем один раз, но c.person_id не является уникальным ключом, так что не мешало бы быть конечно.

Затем мы можем получить все фильмы с участием этих актеров. Мы можем фильтровать, чтобы избежать исходной таблицы.

SELECT t.id 
FROM title t 
JOIN cast_info c ON c.movie_id = t.id 
WHERE t.title != 'The Movie' 
    AND c.person_id IN(SELECT c.person_id 
         FROM cast_info c 
         JOIN title t ON c.movie_id = t.id 
         JOIN role_type r ON r.id = c.role_id 
         WHERE t.title = 'The Movie' AND (r.role = 'actress' OR r.role = 'actor')) 

Теперь мы можем вытащить всех актеров из всех этих фильмов и исключить наших оригинальных актеров. Здесь полезно использовать отдельный идентификатор личности. Это потому, что Боб может сыграть главную роль в фильме «Кино». Позже Боб сделал фильм с Джоном и еще один фильм с Джоном, но мы не хотим, чтобы Джон появлялся дважды.

Итак, вот окончательный запрос:

SELECT DISTINCT c.person_id 
FROM cast_info c 
WHERE c.movie_id IN(SELECT t.id 
       FROM title t 
       JOIN cast_info c ON c.movie_id = t.id 
       WHERE t.title != 'The Movie' 
        AND c.person_id IN(SELECT c.person_id 
             FROM cast_info c 
             JOIN title t ON c.movie_id = t.id 
             JOIN role_type r ON r.id = c.role_id 
             WHERE t.title = 'The Movie' AND (r.role = 'actress' OR r.role = 'actor'))) 
    AND c.person_id NOT IN(SELECT c.person_id 
         FROM cast_info c 
         JOIN title t ON c.movie_id = t.id 
         JOIN role_type r ON r.id = c.role_id 
         WHERE t.title = 'The Movie' AND (r.role = 'actress' OR r.role = 'actor')) 

Как я уже говорил раньше, это трудно проверить это без данных, и это очень много таблиц, чтобы сделать простой SQL скрипку, поэтому, пожалуйста, попробуйте они в битах, как я написал их, если они не работают, и дайте мне знать, что, возможно, потребуется изменить.

+0

Привет! Я очень признателен, что вы не спешите отвечать на мои вопросы. Прошу прощения за то, что вы так много спрашиваете (у меня есть даже больше, чем это, честно)! Мой инструктор бросился по SQL очень быстро, и вы не поверите, что количество людей также борется за это задание; потому что никто не заканчивал его, он был отложен 3 раза уже (удивительно?). Во всяком случае, вернемся к теме ... Я протестировал ваш запрос (после добавления, как 3 отсутствующих скобки в конце), и, похоже, не возвращает строк. Я дам вам знать, могу ли я выяснить, где ошибка. –

+0

О, боже, извините за недостающие парсеры. Это моя ошибка. Когда это присвоение должно? – AdamMc331

+0

Ух ... сегодня в полночь. Не беспокойтесь слишком много о том, чтобы помочь мне, но я уверен, у вас есть свои битвы, чтобы сражаться! –

Смежные вопросы