Postgresql 如何连接这些表以获得正确的输出?

Postgresql How do I join these tables to get the correct output?

我想找出哪些人被认为是电影中的主要演员,但没有被认为是该电影中的角色。

我的架构是:

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

到目前为止,我使用的查询对某些演员有效,但我认为我做的连接不正确,因为有另一个演员是主要演员,但被赋予了一个不应该有的角色(角色名称来自他们所在的另一部电影)。这是我的查询:

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

谁能帮我解决这个问题?

这是结果摘要,联接将所有人物的角色名称添加到他们担任主角的每部电影中。

https://drive.google.com/file/d/1NVRLiYBVbKuiazynx9Egav7c4_VHFEzP/view?usp=sharing

你很接近,但还需要使用 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

从 select 中删除了字符,因为它始终为空。

我认为 table plays 需要第二个连接条件,如下面粗体所示:

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

不过我觉得 not exists 方法会使这个查询更容易理解:

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
        )