使用 IMDB 数据集查找所有与 Yash Chopra 合作制作的电影比任何其他导演都多的演员(转贴)

Find all the actors that made more movies with Yash Chopra than any other director using IMDB dataset (Reposted)

第一个查询 q1 给出了期望的结果。 但是查询 q2 给出了一对演员和导演的电影数量过多。

SELECT * FROM 
   (SELECT  pc.PID AS actorID, pc.Name AS Actor, pd.PID AS directorID,pd.Name AS 
    Director,COUNT(DISTINCT m.MID) count_movie FROM Movie m 
    JOIN 
    M_Cast mc ON m.MID = Trim(mc.MID) 
   JOIN  
   M_Director md ON  m.MID = md.MID
   JOIN  
   Person pc ON Trim(mc.PID) = pc.PID
   JOIN 
   Person pd ON md.PID = pd.PID
   WHERE pd.Name LIKE '%Yash%' GROUP BY pc.Name) AS q1

   JOIN

   (SELECT  pc.PID AS actorID,pc.Name Actor,pd.PID AS directorID,pd.Name AS Director, COUNT(DISTINCT 
   m.MID) count_movie FROM Movie m 
   JOIN 
   M_Cast mc ON  m.MID = TRIM(mc.MID ) 
   JOIN  
   M_Director md ON m.MID = md.MID 
   JOIN 
   Person pc ON TRIM(mc.PID) = pc.PID 
   JOIN 
   Person pd  ON md.PID = pd.PID
   WHERE pd.Name NOT LIKE '%Yash%' GROUP BY pc.PID) AS q2
   ON q1.Actor = q2.Actor ORDER BY q1.count_movie DESC
        actorID     Actor          directorID   Director      count_movie  actorID      Actor      directorID    Director       count_movie
   0    nm0707271   Jagdish Raj    nm0007181    Yash Chopra   11           nm0707271    Jagdish Raj nm0474806   Gulshan Kumar   98
   1    nm0471443   Manmohan       nm0007181    Yash Chopra   10           nm0471443    Manmohan    nm0695153   T. Prakash Rao  39
   2    nm0407002   Iftekhar       nm0007181    Yash Chopra    9           nm0407002    Iftekhar    nm1065099   C.P. Dixit      93
   3    nm0534501   Madan Puri     nm0007181    Yash Chopra    8           nm0534501    Madan Puri  nm0619050   Hiren Nag       94

最右边的 movie_count 似乎高得离谱。如果必须匹配答案,第一行应该小于 11。

这里我没有使用上面的WHERE条件只是为了说明我的查询哪里错了。 即使我使用 Where 条件

where q1.count_movie > q2.count_movie

我得到的结果是

        Name            count
    0   Sanjeev Kumar   3
    1   Sanjeev Kumar   3
    2   Sanjeev Kumar   3
    3   Sanjeev Kumar   3
    4   Ashok Kumar     2

下面的输出是正确的结果。 它将给出 245 行。我只显示了 6 行。

                Name            count
       0        Jagdish Raj     11
       1        Manmohan        10
       2        Iftekhar        9
       3        Shashi Kapoor   7
       4        Rakhee Gulzar   5
       5        Waheeda Rehman  5

给出的表格是

我是sql的新人,在调试代码时遇到了很多麻烦。 请帮助我理解逻辑。

查询第二部分的问题是您汇总了所有其他导演的所有电影,而不是计算每个导演的电影。

我看到了两种完成任务的方法:

  1. 每位演员将 Yash Chopra 的电影数量与所有其他演员进行比较。 (这需要 WHERE yash_chopra_count > ANY (...),但 SQLite 没有 ANY 关键字。)或者将 Yash Chopra 的电影数量与其他人的最大电影数量进行比较。 (这在 SQLite 中有效。)
  2. 按电影数量对每个演员的导演进行排名,看看排名最好的演员是否是 Yash Chopra。 (应该用 ROW_COUNT 完成)。

在我们开始之前,让我们检查一下,如果我们做对了一切:数据模型允许每部电影有多个导演。但我们仍然可以数数。如果一个演员和 Yash Chopra 一起拍了三部电影,和 I. S. Johar 拍了三部电影,我们不在乎这些是六部独立的电影还是可能只有三部电影,而 Yash Chopra 是 I. S. Johar 的助理导演。在我的演员示例中,我们看到另一位导演的电影数量至少与 Yash Chopra 一样多,所以我们不想 select 这个演员。 m:n 关系因此没有障碍。没什么区别。

既然我们已经确定可以简单地计算每个演员和导演的电影数量,让我们看看这两种方法:

将 Yash Chopra 计数与其他最大计数进行比较

如前所述,我们必须聚合其他控制器两次(一次用于每个控制器的计数,一次用于最大计数),因为 SQLite 缺少 ANY 运算符。不过,当我们使用 CTE 来提高可读性时,这并不是什么大问题。

with director_actor as
(
  select
    c.pid as pid_actor,
    d.pid as pid_director,
    count(*) as movie_count
  from m_director d
  join m_cast c on c.mid = d.mid
  group by c.pid, d.pid
)
select pid_actor, movie_count
from director_actor
where pid_director = (select pid from person where name = 'Yash Chopra')
and movie_count >
(
  select coalesce(max(movie_count), 0)
  from director_actor other
  where other.pid_actor = director_actor.pid_actor
  and other.pid_director <> director_actor.pid_director
);

按电影数量对每个演员的导演进行排名

我们必须采取哪些步骤才能找到有问题的演员?

  1. 计算每个演员和导演的电影数量。
  2. 按演员对导演进行排名。大多数电影的导演排名第一。如果有平局,那么我们将另一位导演排在 Yash Chopra 之后,因此如果 Yash Chopra 的电影比其他导演多,他只会排名第一。
  3. 保留最佳导演是 Yash Chopra 的演员。

对于排名,我会使用 ROW_NUMBER

with ranked as
(
  select
    c.pid as pid_actor,
    d.pid as pid_director,
    yc.pid as pid_yash_chopra,
    count(*) as movie_count,
    row_number() over (partition by c.pid order by count(*) desc, d.pid = yc.pid) as rn
  from m_director d
  join m_cast c on c.mid = d.mid
  left join person yc on yc.pid = d.pid and name = 'Yash Chopra'
  group by c.pid, d.pid, yc.pid
)
select pid_actor, movie_count
from ranked
where rn = 1 and pid_director = pid_yash_chopra;