首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >选择所有指定演员一起工作的电影

选择所有指定演员一起工作的电影
EN

Code Review用户
提问于 2016-04-19 19:09:30
回答 2查看 9.4K关注 0票数 5

下面是我写的一个查询,试图找出三个演员一起出演过的所有电影:

代码语言:javascript
复制
select distinct
    Movie
from 
    CastMember
where 
    Movie in (
        select Movie
        from CastMember
        where Actor = 1
    )
    and Movie in (
        select Movie
        from CastMember
        where Actor = 2
    ) 
    and Movie in (
        select Movie
        from CastMember
        where Actor = 3
    )

电影和演员是电影和演员表的FKs。CastMember只有两列:电影和演员。

有更好的方法来写这个吗?

更新:仅仅使用INTERSECT的想法

代码语言:javascript
复制
select Movie
from CastMember
where Actor = 1
intersect
select Movie
from CastMember
where Actor = 2
intersect
select Movie
from CastMember
where Actor = 3
EN

回答 2

Code Review用户

回答已采纳

发布于 2016-04-19 20:43:55

这能起作用吗?

代码语言:javascript
复制
select m.Title
from Movie m
    inner join CastMember cm on cm.MovieId = m.Id
    inner join Actor a on cm.ActorId = a.Id
where a.Name in ('John Travolta', 'Uma Thurman')
group by m.Title
having count(m.Id) > 1 -- this should be replaced with the number of items in the "in" list minus 1.
票数 6
EN

Code Review用户

发布于 2016-04-19 19:22:50

distinct几乎总是表明出了一些问题。

我在自欺欺人,试图看看为什么这不能产生完全相同的输出:

代码语言:javascript
复制
select Movie from CastMember where Actor in (1,2,3) -- group by Movie

似乎您的模式令人困惑:很难分辨什么是FK,什么来自何处--这可能是我过度简化这里的查询的原因。

让我看看..。我不是一个超级UML迷,所以我可能搞错了,但是假设您有:

然后,您可能希望使用inner join来“链接”表--使用[FKTableName][Id]方案命名FK列,可以更容易地查看IMO的内容:

代码语言:javascript
复制
select m.Title
from Movie m
    inner join CastMember cm on m.Id = cm.MovieId
    inner join Actor a on a.Id = cm.ActorId
where a.Id in (1,2,3)
group by m.Title

现在,上面的简单返回所有的电影演员任何一个演员曾主演-和你想要的电影,所有这些演员一起主演。

我首先使用CastMember表,并选择ActorId 1、2和3的所有行:

代码语言:javascript
复制
select MovieId, ActorId from CastMember where ActorId in (1,2,3)

然后,我知道我期望每部电影有3行-假设这里是Server,我可以使用CTE和一个窗口函数来通过MovieId来划分结果,并对有3行的电影进行筛选:

代码语言:javascript
复制
with filter as (
    select MovieId, row_number() over (partition by MovieId order by MovieId, ActorId) RN
    from CastMember
    where ActorId in (1,2,3))
select MovieId from filter where RN = 3

现在我知道了我想要的Id是什么--如果我将这个select变成另一个CTE,我现在可以从Movie中选择所有行:

代码语言:javascript
复制
with filter as (
    select MovieId, row_number() over (partition by MovieId order by MovieId, ActorId) RN
    from CastMember
    where ActorId in (1,2,3)
)
, movies as (
    select MovieId from filter where RN = 3
)
select m.*
from Movie m
inner join movies on m.Id = movies.MovieId

现在,我不再为乌玛·瑟曼和约翰·特拉沃塔杀死比尔:)

不幸的是,mysql不支持CTE和窗口函数(AFAIK)。同样的方法将使用不那么优雅的嵌套子查询和临时表;我将让mysql审查员想出一种更简洁的方法--无论如何,我仍然建议避免以表命名的列-- " Movie“表中的"Movie”列,意思是"Title",然后在多到多的关联表中使用"Movie“列,其中"Movie”的意思是“Movie表的主键”,当然需要修改。

票数 5
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/126157

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档