我正在处理电影数据库的更多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
我的逻辑在这里完全错了吗?或者是查询的效率非常低效(我在想)。有没有办法解决它运行并得到正确的答案?或者我应该在逻辑上更正确地考虑正确查询的方式吗?
这么多问题,但我想要反馈为什么这个查询不起作用以及下一步是什么。
答案 0 :(得分: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
答案 1 :(得分:1)
这是我的查询,并清楚地说明了如何得出该查询。
第1步:获取Art Garfunkel的所有movieids
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'
答案 2 :(得分:0)
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扮演角色(内部选择)的那些movieids的所有actorids(=外部选择),然后我自己过滤出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并将其传递回 casting-c < / strong>即可。 cast-c 从Art Garfunkel中查找movieids(顺便说一下是两个:1412用于catch-22和1597用于Boxing Helena)并将它们设置为 cast-b <的过滤器/ strong> -as cast-b 接管他们。 Casting-b 然后 - 将过滤器设置为来自Garfunkel的两部电影 - 恢复为 actor-a 中的所有actorID,其中所有演员的名字都已加星标这两部电影都被抬起头来。 最后,Art Garfunkel被过滤掉 - 就是这样。
我觉得这就好像是一些机器代码,好像有些查询优化器已经提出来了。 一个明智的人不会沿着这些思路思考(至少我不会)。
答案 3 :(得分: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'
答案 4 :(得分: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用户抛出了另一个答案。
答案 5 :(得分: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'
答案 6 :(得分:0)
我认为这个问题类似于朱莉安德鲁斯项目(目前sqlzoo上的#13),所以我基本上调整了Bill Karwin的优雅solution to the Julie Andrews problem以一种不太优雅的方式解决这个问题。这个解决方案确实使用了所有JOINs
,这似乎是这套练习的重点。从本质上讲,我对此进行概念化的方式是,Art Garfunkel被投放在一部电影中,其他人也被演员。换句话说,Garfunkel&lt; - &gt;铸造&lt; - &gt;电影&lt; - &gt;铸造&lt; - &gt;联合主演的名字。
我是一个非常新的SQL用户(老实说,&lt; 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
答案 7 :(得分: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')
答案 8 :(得分: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'
答案 9 :(得分:0)
您的两种解决方案都不完全错误。你只需要为你的sql添加一个条件。 QThread
这意味着只找到那些使用List all the people who have worked with 'Art Garfunkel'
的人,但是在你的sql中你没有从列表中排除'Art Garfunkel'
,这就是为什么sqlzoo说你的解决方案是错误的。
这是您的修改版本:
'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')
AND a.name <> 'Art Garfunkel'
已添加到原始sql
你的解决方案#2:
AND a.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')
AND actor.name <> 'Art Garfunkel'
已添加到原始sql
答案 10 :(得分: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')
答案 11 :(得分:0)
None