Reputation: 147
I am trying to find out which people are noted as being principal actors in a movie, but aren't noted as playing a character in that movie.
The schema I have is:
CREATE TABLE public.movies (
id integer NOT NULL,
title text NOT NULL,
year_made public.yeartype NOT NULL,
runtime public.minutes,
rating double precision,
nvotes public.counter
);
CREATE TABLE public.people (
id integer NOT NULL,
name text NOT NULL,
year_born public.yeartype,
year_died public.yeartype
);
CREATE TABLE public.plays (
movie_id integer NOT NULL,
person_id integer NOT NULL,
"character" text NOT NULL
);
CREATE TABLE public.principals (
movie_id integer NOT NULL,
ordering public.counter NOT NULL,
person_id integer NOT NULL,
role text NOT NULL
So far the query I have used works for some actors, however I think I have done the joins incorrectly as there is another actor who is a principal actor but is given a character which it shouldn't have (character name is from another movie they were in). This is my query:
select name as actor, movies.title as movie,character
from principals
inner join people on principals.person_id=people.id
inner join movies on principals.movie_id=movies.id
left outer join plays on principals.person_id=plays.person_id
where principals.role = 'actor' and character is null
Can anyone help me with this?
This is a summary of results and the join adds all the persons character names to every movie they were principal in.
https://drive.google.com/file/d/1NVRLiYBVbKuiazynx9Egav7c4_VHFEzP/view?usp=sharing
Upvotes: 0
Views: 87
Reputation: 35603
I think a second join condition is required for table plays
as shown in bold below:
FROM principals LEFT JOIN plays ON principals.person_id = plays.person_id AND principles.movie_id = plays.movie_id WHERE principals.role = 'actor' AND plays.person_id IS NULL
However I feel that a not exists
approach will make this query easier to understand:
SELECT
people.name AS actor
, movies.title AS movie
, plays.character
FROM principals
INNER JOIN people ON principals.person_id = people.id
INNER JOIN movies ON principals.movie_id = movies.id
WHERE principals.ROLE = 'actor'
AND NOT EXISTS (
SELECT NULL
FROM plays
WHERE principals.person_id = plays.person_id
AND principals.movie_id = plays.movie_id
)
Upvotes: 1
Reputation: 425278
You’re pretty close, but need to also join plays using movie.id:
select name as actor, movies.title as movie
from principals
join people on principals.person_id=people.id
join movies on principals.movie_id=movies.id
left join plays on principals.person_id=plays.person_id
and movies.id=principals.movie_id
where principals.role = 'actor'
and character is null
Removed character from select because it’s always null.
Upvotes: 0