SQL查询查找Kevin Bacon的数字为2

时间:2012-02-03 22:18:24

标签: sql sql-server sql-server-2008 select subquery

使用IMDB数据库,我有表actorcastsmovie,我需要选择Kevin Bacon数为2的演员。我认为应该这样做,但我得到0行返回。我的错误是什么?

select fname, lname
from actor join casts on pid=actor.id
where actor.id in (
    select a3.id  --actors who have a kb number of 2
    from casts c3 join actor a3 on c3.pid=a3.id,
    (
     (select c1.mid --actors who have a kb number of 1
     from (casts c1 join actor a1 on c1.pid=a1.id), (casts c2 join actor a2 on c2.pid=a2.id)
     where c1.mid=c2.mid and a2.fname='Kevin' and a2.lname='Bacon')
    )Level1 where c3.mid=Level1.mid
)
and actor.id not in (select a4.id --and only a kb number of 2
     from (casts c4 join actor a4 on c4.pid=a4.id), (casts c5 join actor a5 on c5.pid=a5.id)
     where c4.mid=c5.mid and a5.fname='Kevin' and a5.lname='Bacon');

以下是表格模式:

ACTOR (id, fname, lname, gender)
MOVIE (id, name, year)
CASTS (pid, mid, role)

mid是电影ID的外键,pid是演员ID的外键。

请注意,对问题的限制禁止我使用临时表或递归:查询应该使用子选择。


我也试过

select count(distinct pid) from casts join actor on pid=actor.id where mid in (
    select mid from casts where pid in (
        select distinct pid from casts where mid in (
            select mid from casts join actor on pid=actor.id where fname='Kevin' and lname='Bacon')))

and pid not in  
    (select distinct pid from casts where mid in (
        select mid from casts join actor on pid=actor.id where fname='Kevin' and lname='Bacon'));

这似乎也应该有用,但它还没有完成。


我终于设法获得了一些工作代码:

select count(distinct pid) from casts where mid in (
    select mid from casts where pid in (
        select distinct pid from casts where mid in (
            select mid from casts join actor on pid=actor.id where fname='Kevin' and lname='Bacon')))

and pid not in  
    (select distinct pid from casts where mid in (
        select mid from casts join actor on pid=actor.id where fname='Kevin' and lname='Bacon'));

子查询至少会返回合理的答案。但这需要永远。每个子查询花了不到30秒,但他们一起花了6分钟计算。为什么呢?


注意:这是作为家庭作业给我的。为了避免任何学术不端行为的混乱,我更愿意,如果人们没有发布完整/准确的解决方案,而是指出我做错的一般事情/就我应该如何解决这个问题提出一般性建议

2 个答案:

答案 0 :(得分:9)

为了给出解决方案的草图而不是精确的解决方案,我将使用这种通用方法

SELECT *
FROM   ACTOR
WHERE  id IN (
SELECT id 
       /* ... of actors that have worked on a film worked 
         on by actors that have worked on a KB film*/
EXCEPT
SELECT id
 /* ... of all actors that have worked on a KB film
         including KB himself*/ )

另外,因为你不允许使用递归CTE,所以这里是一个答案。

WITH RecursiveCTE
     AS (SELECT C.pid,
                C.mid,
                0 as Level
         FROM   CASTS C
                JOIN ACTOR A
                  ON A.id = C.pid
         WHERE  A.fname = 'Kevin'
                and A.lname = 'Bacon'
         UNION ALL
         SELECT c1.pid,
                c2.mid,
                R.Level + 1
         FROM   RecursiveCTE R
                JOIN CASTS c1
                  ON c1.mid = R.mid
                     AND R.Level < 2
                JOIN CASTS c2
                  ON c1.pid = c2.pid)
SELECT *
FROM   ACTOR
WHERE  id IN (SELECT pid
              FROM   RecursiveCTE
              GROUP  BY pid
              HAVING MIN(Level) = 2)  

答案 1 :(得分:0)

这正确吗?

select distinct name from M_Cast c1 join M_Cast c2 on c2.mid=c1.mid
join M_cast  c3 on c2.pid=c3.pid join M_Cast c4 on c4.mid=c3.mid 
join person p on p.pid= trim(c4.pid) where  trim(c1.pid)="nm0451321" and p.pid!="nm0451321"

select distinct trim(name) from M_Cast c1 join M_Cast c2 on c1.mid=c2.mid
join person p on p.pid= trim(c2.pid) where  trim(c1.pid)="nm0451321" and p.pid!="nm0451321"

nm0451321 --->凯文·培根的ID