2

我正在使用电影数据库进行更多的 JOIN 操作。我的问题是关于问题 #16:列出所有与“Art Garfunkel”合作过的人

您需要首先获取 Art Garfunkel 所在的所有电影作为一个值,然后通过将其与第一个值进行比较来获取同一部电影中的所有人员姓名。

我提出了自己的查询,按逻辑它应该可以工作,但不是由于超时(我假设这是由于查询效率低下)

我的查询:

SELECT DISTINCT a.name
FROM actor a
JOIN casting b ON (a.id=b.actorid) 
JOIN movie c ON (b.movieid=c.id)
WHERE c.title IN(SELECT z.title
FROM movie z
JOIN casting y ON (z.id=y.movieid)
JOIN actor x on (y.actorid=x.id)
WHERE x.name='Art Garfunkel')

另一个版本:

SELECT DISTINCT actor.name
FROM movie,actor,casting
WHERE movie.id=casting.movieid
AND actor.id=casting.actorid
AND movie.title IN(SELECT movie.title
FROM movie,actor,casting
WHERE movie.id=casting.movieid
AND actor.id=casting.actorid
AND actor.name='Art Garfunkel')

这两个都会引发解析错误,说明尝试查询上面显示的内容时出现超时。

他们提供的被接受为答案的查询版本是:

SELECT DISTINCT d.name
FROM actor d JOIN casting a ON (a.actorid=d.id)
   JOIN casting b ON (a.movieid=b.movieid)
   JOIN actor c ON (b.actorid=c.id 
                AND c.name='Art Garfunkel')
  WHERE d.id!=c.id

我的逻辑在这里完全错误吗?还是查询效率非常低(我在想)。有没有办法修复它以运行并获得正确答案?还是我应该按照正确查询的方式更合乎逻辑地思考?

有很多问题,但我想就为什么该查询不起作用以及下一步是什么提供反馈。

4

12 回答 12

1

以下是所有 sql zoo 问题的答案: answers

SELECT a.name
 FROM casting c JOIN actor a ON
  a.id = c.actorid
 WHERE 
  a.name <> 'Art Garfunkel' AND
  c.movieid 
 IN (
  SELECT m.id
     FROM casting c JOIN movie m ON
       m.id = c.movieid
     JOIN actor a ON
       c.actorid = a.id
     WHERE a.name = 'ART Garfunkel'
)
ORDER BY a.name
于 2013-03-17T22:33:08.180 回答
1

这是我的查询以及如何得出它的清晰解释。

第 1 步:获取所有movieidsArt Garfunkel

select movie.id 
from actor 
     join 
     casting on actor.id=casting.actorid 
     join 
     movie on movie.id=casting.movieid
where actor.name='Art Garfunkel'
group by movie.id

第 2 步:现在从这些列表中movieids获取这些电影中的所有演员。

  select actor.name 
  from casting 
       join 
       actor on casting.actorid=actor.id 
       join 
       movie on movie.id=casting.movieid
 where casting.movieid in
                       ( select movie.id 
                         from actor 
                              join 
                              casting on actor.id=casting.actorid 
                              join 
                              movie on movie.id=casting.movieid
                         where actor.name='Art Garfunkel'
                         group by movie.id
                      )

第 3 步:我们需要合作者从结果集中'Art Garfunkel'消除'Art Garfunkel'

     select actor.name 
     from casting 
           join 
           actor on casting.actorid=actor.id 
           join 
           movie on movie.id=casting.movieid
     where casting.movieid in
                           ( select movie.id 
                             from actor 
                                  join 
                                  casting on actor.id=casting.actorid 
                                  join 
                                  movie on movie.id=casting.movieid
                             where actor.name='Art Garfunkel'
                             group by movie.id
                          )
   and actor.name!='Art Garfunkel'
于 2018-12-18T01:59:05.760 回答
0

好吧,我花了几个小时才真正弄清楚这个(第 16 号),因为建议的解决方案乍一看没有意义(第二次也没有)。但是,在我想出自己的解决方案后,我设法弄清楚了,这更容易理解(我觉得)。所以首先我的解决方案:

select name from actor 
join casting on actor.id=actorid
where movieid in
(select movieid from casting
join actor on actorid=actor.id
where name='Art Garfunkel')
and name <>'Art Garfunkel'

我为 Art Garfunkel 在其中扮演角色(内部选择)的那些 movieid 搜索所有 actorid(= 外部选择),然后我过滤掉 Art Garfunkel 本人。

很简单。

您可以在查询末尾添加以下行,这会很好:

order by name

但随后查询不再被接受为正确的。

当我不理解其他人的解决方案时,这让我很烦恼,所以我花了一些时间在其他地方给出的解决方案上。这里又是:

SELECT DISTINCT a.name
FROM actor a 
JOIN casting b ON (a.id=b.actorid)
JOIN casting c on b.movieid=c.movieid
JOIN actor d ON (c.actorid=d.id 
                AND d.name='Art Garfunkel')
WHERE a.id!=d.id

有趣的是,您可以编写稍微不同的代码并将 where 子句从最后一个连接中取出:

SELECT DISTINCT a.name
FROM actor a 
JOIN casting b ON (a.id=b.actorid)
JOIN casting c on b.movieid=c.movieid
JOIN actor d ON (c.actorid=d.id)
WHERE d.name='Art Garfunkel' 
AND a.id!=d.id

在任何情况下,您都必须向后看这个查询,否则它永远没有意义。这似乎是发生了什么:

actor-d(或 Where 子句的第一部分,似乎首先被评估)设置(或限制)Art Garfunkel 并将其传递回cast-ccast-c查找来自 Art Garfunkel 的 movieid(顺便说一下,有两个:catch-22 为 1412,Boxing Helena 为 1597)并将它们设置为 cast-b 的过滤器——因为cast-b接管了它们。 然后Casting-b(过滤器设置为 Garfunkel 的这两部电影)返回到actor-a中的所有 actorid ,在其中查找在这两部电影中出演过的所有演员的姓名。最后,Art Garfunkel 被过滤掉了——就是这样。

对我来说,这好像是一些机器代码,好像是某个查询优化器想出了它。一个明智的人不会按照这些思路思考(至少我不会)。

于 2014-10-25T18:07:08.200 回答
0
SELECT name
  FROM movie, casting, actor
  WHERE movieid=movie.id
    AND actorid=actor.id 
and movieid IN
    (SELECT movieid FROM casting, actor
     WHERE actorid=actor.id
     AND name='Art Garfunkel')and name <>'Art Garfunkel'
于 2015-05-07T10:09:06.227 回答
0

以下是上面给出的SQL答案:

SELECT a.name from actor a 
inner join casting c on a.id=c.actorid 
inner join movie m on m.id=c.movieid 
WHERE m.id in (SELECT c.movieid from casting c inner join actor a 
on a.id=c.actorid WHERE a.name='Art Garfunkel') 
and a.name<>'Art Garfunkel'

然而,作为一个还在习惯联合的 SQL 初学者,我想出的第一个代码如下:

SELECT name from actor WHERE id IN 
(SELECT actorid from casting WHERE movieid IN (SELECT movieid 
from casting WHERE actorid IN (SELECT 
id from actor WHERE name='Art Garfunkel'))) 
and name<>'Art Garfunkel'

它本质上与上面的解释做同样的事情——SELECT id语句查找 Art 的演员 id。SELECT movieid查找他所在的电影。SELECT actorid查找这些电影中的其他演员,而SELECT name查找他们的名字。

学习如何进行联合是理想的,我最终得到了内部连接语法,但只是为更熟悉 SELECT 或仍在学习联合的 SQL 用户提供了另一个答案。

于 2015-05-13T00:33:35.917 回答
0

另一个有效的解决方案如下:

SELECT name
FROM casting
JOIN actor ON actor.id=actorid
WHERE movieid IN (SELECT movieid FROM casting WHERE actorid = 
   (SELECT id FROM actor WHERE name='Art Garfunkel'))
GROUP BY actorid
HAVING name<>'Art Garfunkel'
于 2015-10-12T09:52:47.360 回答
0

您的两种解决方案都不是完全错误的。您只需要在 sql 中再添加一个条件。List all the people who have worked with 'Art Garfunkel'这意味着只找到那些与之合作'Art Garfunkel'但在你的 sql 中你没有'Art Garfunkel'从列表中排除的人,这就是为什么 sqlzoo 说你的解决方案是错误的。

这是您的修改版本:

SELECT DISTINCT a.name
 FROM actor a
             JOIN casting b ON (a.id=b.actorid) 
             JOIN movie c ON (b.movieid=c.id)
 WHERE c.title IN(SELECT z.title
                   FROM movie z
                                JOIN casting y ON (z.id=y.movieid)
                                JOIN actor x on (y.actorid=x.id)
                   WHERE x.name='Art Garfunkel') 
 AND a.name <> 'Art Garfunkel'

AND a.name <> 'Art Garfunkel'被添加到你原来的 sql

你的解决方案#2:

SELECT DISTINCT actor.name
 FROM movie,actor,casting
 WHERE movie.id=casting.movieid
       AND actor.id=casting.actorid
       AND movie.title IN(SELECT movie.title
                           FROM movie,actor,casting
                           WHERE movie.id=casting.movieid
                                 AND actor.id=casting.actorid
                                 AND actor.name='Art Garfunkel')
       AND actor.name <> 'Art Garfunkel'

AND actor.name <> 'Art Garfunkel'被添加到你原来的 sql

于 2016-12-23T01:19:08.573 回答
0

一个简单的解决方案是 - select distinct(name) from movie join casting on movie.id=movieid join actor on actor.id=actorid where name not in ('Art Garfunkel') and title in (select title from movie join casting on movie.id=movieid join actor on actor.id=actorid where name ='Art Garfunkel')

于 2018-01-31T08:51:12.293 回答
0

我认为这个问题类似于 Julie Andrews 项目(#13 目前在sqlzoo上),所以我基本上改编了Bill Karwin对 Julie Andrews 问题的优雅解决方案,以一种公认的不太优雅的方式解决这个问题。这个解决方案确实使用JOINs了这组练习的重点。从本质上讲,我对此的概念化方式是,Art Garfunkel 曾出演过其他人也出演过的电影。换句话说,加芬克尔 <-> 演员 <-> 电影 <-> 演员 <-> 联合主演的名字。

我是一个非常新的 SQL 用户(老实说,<24 小时)所以这可能很笨拙,但它对我有用:

SELECT a2.name
FROM actor a1
JOIN casting AS c1 ON (a1.id = c1.actorid)
JOIN movie ON (c1.movieid=movie.id)
JOIN casting AS c2 ON (movie.id=c2.movieid)
JOIN actor AS a2 ON (c2.actorid=a2.id)
WHERE
    a1.name='Art Garfunkel'
    AND a2.name <> 'Art Garfunkel'
GROUP BY a2.name
于 2016-02-28T07:28:47.887 回答
0
SELECT a.name FROM actor a 
    JOIN casting c ON a.id=c.actorid 
    JOIN movie m ON c.movieid=m.id
    WHERE c.movieid IN 
        (SELECT movieid FROM casting WHERE actorid IN
            (SELECT id FROM actor WHERE name = 'Art Garfunkel')) 
    AND a.name <> 'Art Garfunkel'
于 2016-07-25T15:05:38.127 回答
0
SELECT DISTINCT name
FROM actor, movie, casting
WHERE name <> 'Art Garfunkel'
AND movie.id = casting.movieid AND casting.actorid = actor.id
AND movieid IN (
SELECT movieid 
        FROM casting, actor 
        WHERE actor.id = actorid AND name = 'Art Garfunkel'
)
于 2019-11-29T01:13:45.007 回答
0

我不明白为什么需要在此查询中加入电影表。本练习中的任务是仅列出演员姓名,而不是姓名和头衔(这也需要加入电影表)。我想出了以下查询,它有效。:)

SELECT name 
FROM actor 
JOIN casting on actor.id = actorid 
WHERE name <> 'Art Garfunkel' 
AND movieid IN 
(SELECT movieid 
FROM casting 
JOIN actor on actorid = actor.id 
WHERE name = 'Art Garfunkel')
于 2016-07-01T14:22:55.033 回答