2012-02-03 3 views
24

Sử dụng cơ sở dữ liệu IMDB, tôi có bảng actor, castsmovie và tôi cần chọn diễn viên có số Kevin Bacon là 2. Tôi nghĩ điều này nên làm, nhưng tôi nhận được 0 hàng trả về. Lỗi của tôi là gì?Truy vấn SQL để tìm số Kevin Bacon số 2

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'); 

Dưới đây là các lược đồ bảng:

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

mid là khóa ngoại đến một id phim và pid là khóa ngoại để id diễn viên.

Lưu ý rằng các hạn chế đối với câu hỏi không cho phép tôi sử dụng bảng tạm thời hoặc đệ quy: truy vấn nên được thực hiện với các lựa chọn con.


Tôi cũng đã cố gắng

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')); 

mà cũng có vẻ như nó nên làm việc, nhưng nó không hoàn thành.


Cuối cùng tôi quản lý để có được một số mã làm việc:

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')); 

Các truy vấn con trở lại câu trả lời hợp lý, ít nhất. Nhưng nó sẽ mãi mãi. Mỗi truy vấn con mất dưới 30 giây, nhưng chúng lại mất 6 phút và đếm được. Tại sao?


Lưu ý: Điều này đã được trao cho tôi làm bài tập về nhà. Để tránh bất kỳ hành vi sai trái nào về hành vi sai trái của tôi, tôi thích nếu mọi người không đăng các giải pháp hoàn chỉnh/chính xác, nhưng chỉ ra những điều chung mà tôi đang làm sai/đưa ra các đề xuất chung về cách tôi nên thực hiện .

+2

@AbeMiessler http://sqlfiddle.com/ – scottm

+0

làm cho một trường hợp thử nghiệm: tạo bảng TEMP với dữ liệu – cetver

+0

aww, và ở đây tôi chỉ tìm ra cách để làm điều đó với một CTE đệ quy quá (điều này rất thú vị trong bối cảnh xử lý đồ thị theo chu kỳ) ... Tại sao bạn không được phép sử dụng chúng? Mặc dù, không phải là một số cơ sở dữ liệu không phải SQL mới phải làm tốt hơn ở loại điều này - mặc dù ai đó đã tạo ra một cơ sở dữ liệu biểu đồ mạng? Bạn có được phép sử dụng CTE không? –

Trả lời

9

Để cung cấp một phác thảo của một giải pháp chứ không phải là một giải pháp chính xác tôi sẽ sử dụng phương pháp chung này

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*/) 

Cũng như bạn không được phép sử dụng CTEs đệ quy anyway đây là một câu trả lời bằng những.

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) 
+0

tìm kiếm ý tưởng tổng quát hơn: những gì tôi đang làm sai/những gì tôi nên làm, nhưng tôi sẽ chạy truy vấn của bạn và bỏ phiếu cho bạn nếu câu trả lời khớp với trả lời tôi (hy vọng, cuối cùng) nhận được. – Colleen

+0

Hmmm đây vẫn là một câu trả lời thực tế, mà tôi nghĩ rằng anh ta muốn tránh. – ErikE

+0

Đây là câu trả lời thực tế, nhưng tôi đã đăng bình luận đó sau khi anh ấy đăng câu trả lời, vì vậy nó ổn. – Colleen