SQL查询未返回所需结果 - 电影数据库查询

时间:2015-02-03 23:07:35

标签: sql database

我有这张桌子:

actors(id: int, first_name: string, last_name: string, gender: string)
directors(id: int, first_name: string, last_name: string)
directors genres(director id: int, genre: string, prob: float)
movies(id: int, name: string, years: int, rank: float)
movies directors(director id: int, movie id: int)
movies genres(movie id: int, genre: string)
roles(actor id: int, movie id: int, role: string)

我想找到2002年威尔逊叶执导的所有喜剧电影中的演员名单。

我正在做以下事情:

select distinct A.first_name, 
       A.last_name, 
       M.name
  from actors A inner join roles R 
                      on A.id=R.actor_id
                inner join movies M 
                      on M.id=R.movie_id
  where M.name in ( select M.name
                      from movies M inner join movies_genres G 
                                       on M.id = G.movie_id
                                    inner join movies_directors MD 
                                       on M.id = MD.movie_id
                                    inner join directors D 
                                       on D.id = MD.director_id
                     where G.genre = 'Comedy' 
                       and M.year = 2002 
                       and D.first_name='Wilson' 
                       and D.last_name='Yip');

但是,这给了我2002年威尔逊执导的一部喜剧电影中的演员名单,但是我希望演员能够扮演'所有'这样的喜剧。

怎么做?

3 个答案:

答案 0 :(得分:0)

首先,让我们找出数量: 2002年由Wilson Yip执导的喜剧。我们正在这样做,以确定哪些演员在所有演员中演出(后来):


declare @totalNumberOfMovies as int =(
Select count(*) 
from 
movies m
inner join 
movies_genres  mg
on m.movie_id=mg.movied_id
inner join movies_directors md
on mg.movie_id=md.movie_id
inner join directors d
on md.director_id=d.director_id
where mg.genre='Comedy' and  d.first_name='Wilson' and d.last_name='Yip' and m.year='2002'
);

由Wilson Yip在2002年执导的喜剧总数已分配给变量。

现在,你必须加入你需要的所有表(包括所有过滤器),按行者的名字和姓氏分组,并包括“有计数(*)”过滤器,其值必须等于先前定义的变量@totalNumberOfMovies

它只会让你扮演所有电影的演员。而不是使用变量,你可以使用子查询。

问候; - )

答案 1 :(得分:0)

您可以使用子查询计算此类电影的数量,并将其放入having子句中,例如:

select a.first_name, a.last_name, m.name
  from (select r.actor_id
          from movies M
          join movies_genres G
            on M.id = G.movie_id
          join movies_directors MD
            on M.id = MD.movie_id
          join directors D
            on D.id = MD.director_id
          join roles r
            on r.movie_id = m.id
         group by r.actor_id
        having count(*) = (select count(*) as num_of_movies
                            from movies M
                            join movies_genres G
                              on M.id = G.movie_id
                            join movies_directors MD
                              on M.id = MD.movie_id
                            join directors D
                              on D.id = MD.director_id
                           where G.genre = 'Comedy'
                             and M.year = 2002
                             and D.first_name = 'Wilson'
                             and D.last_name = 'Yip')) x
  join actors a
    on a.id = x.actor_id
  join roles r
    on a.id = r.actor_id
  join movies m
    on m.id = r.movie_id

或者,您可以将该子查询作为from放入inline view子句中,并将其连接到另一个内联视图,其中计算每个actor的计数,然后将其连接回原始表中你想要的字段,如:

select a.first_name, a.last_name, m.name
  from (select r.actor_id, count(*) as movies_this_actor
          from movies M
          join movies_genres G
            on M.id = G.movie_id
          join movies_directors MD
            on M.id = MD.movie_id
          join directors D
            on D.id = MD.director_id
          join roles r
            on r.movie_id = m.id
         group by r.actor_id) x
  join (select count(*) as movies_total
          from movies M
          join movies_genres G
            on M.id = G.movie_id
          join movies_directors MD
            on M.id = MD.movie_id
          join directors D
            on D.id = MD.director_id
         where G.genre = 'Comedy'
           and M.year = 2002
           and D.first_name = 'Wilson'
           and D.last_name = 'Yip') y
    on x.movies_this_actor = y.movies_total
  join actors a
    on a.id = x.actor_id
  join roles r
    on a.id = r.actor_id
  join movies m
    on m.id = r.movie_id

答案 2 :(得分:0)

这个SQL可以进行优化,但粗略地说,如果你使用的是Oracle,你可以尝试类似下面的内容。

with wilson_yip_2002_comedies as
  (
    select m.id
    from movies m, movies_genres mg, movies_directors md, directors d
    where m.id = mg.movie_id
    and m.id = md.movie_id
    and md.director_id = d.id
    and mg.genre = 'Comedy'
    and m.years = 2002
    and d.first_name = 'Wilson'
    and d.last_name = 'Yip'
)
select a.id, a.first_name, a.last_name, count(r.movie_id) n_movies
from actors a, roles r, wilson_yip_2002_comedies
where a.id = r.actor_id
and r.movie_id = wilson_yip_2002_comedies.id
group by a.id, a.first_name, a.last_name
having count(r.movie_id) = (
  select count(1) 
  from wilson_yip_2002_comedies);

步骤:

  • 基本上你可以获得Wilson Yip所指导的所有喜剧 2002年,然后通过角色与演员交叉。那会 给你任何在至少一部电影中扮演角色的演员。
  • 但是因为你想要演员参与所有电影,你可以 由movie_id分组并添加一个HAVING条件来过滤 结果是为了选择那些喜剧电影中的一部分 正如Wilson Yip在2002年所执导的那样。
  • 因为你事先没有喜剧的数量,所以你 需要一个查询来获取它。

如果你不能使用WITH,你可以写两次整个查询,虽然这不是很整洁。

请尝试提供一种简单的方法来尽可能地重现您的问题,例如SQLFiddle。

http://sqlfiddle.com/#!4/4b05c/5

希望这有帮助。