我想要每位导演超过20部电影的男性导演的名字,并且已经投放了他指导的每部电影。如果他投了一部电影,但没有指导它,那没关系,我仍然想要他的名字;如果他导演任何电影但没有投入,我不再想要他了。
SELECT p.firstname,
p.lastname
FROM person p
WHERE p.gender = 'M' AND
(
SELECT COUNT(*)
FROM filmparticipation fpd
WHERE p.personid = fpd.personid AND
fpd.parttype = 'director' AND
(
SELECT COUNT(*)
FROM filmparticipation c
WHERE c.personid = fpd.personid AND
c.filmid = fpd.filmid AND
c.parttype = 'cast'
) > 0
) >= 20;
这只是我多次尝试之一。作为一个附带问题,为什么它不起作用?我确保我正在检查正确的导演电影ID到演出的电影ID等。
答案 0 :(得分:1)
看起来像这样:
SELECT p.firstname, p.lastname
FROM person p
JOIN (
SELECT fd.personid
FROM filmparticipation fd
LEFT JOIN filmparticipation fc USING (personid, filmid)
WHERE fd.parttype = 'director'
AND fc.parttype = 'cast'
GROUP BY fd.personid
HAVING count(*) > 20 -- 21+ movies directed (NULL not counted)
AND NOT bool_or(fc.personid IS NULL) -- no movie directed but not cast
) AS fp USING (personid)
WHERE p.gender = 'M';
在子查询I LEFT [OUTER] JOIN
中,同一部影片的同一个人所指向并投下的所有行 - 他只指向其余部分的地方填充NULL
。这就是LEFT JOIN
的作用。这假设同一个人只能在同一部电影的同一个角色中出现一次(UNIQUE或PK约束!)。
按personid
分组必须产生超过20行,并且所有投射personid
都不能NULL
。 JOIN
到人员表并限制男性,你就完成了。
有很多方法可以解决它,这个应该是最快的方法之一。