2010-02-19 7 views
8

이 문제가 있습니다. 사용자의 이름 아래 같은 사용자의 FRIENDNAME를 포함하는 소셜 네트워크와 friends 테이블에 사용자의 이름으로 구성 users 테이블 ...Oracle SQL 내 네트워크 (친구 또는 친구의 친구)에있는 사용자가 있는지 확인하는 SQL 문을 작성하는 방법

username friendname 

John  Thomas 
Chris  James 

을 감안할 때 ... 나는 SQL 문을 작성하려고 해요 사용자가 내 네트워크에있는 경우에 해당됩니다. 즉 은 해당 사용자가 친구 또는 친구의 친구입니까?

나는이 문제를 해결 춤을 봤는데 만이 쿼리와 함께 올 수 : 거짓 경우 내 친구의 친구의 경우 사용자가 즉 단지 null을 반환하는 경우

SELECT f2.username, f2.friendname 
FROM friends f2 
WHERE f2.username IN (
     SELECT f1.friendname 
     FROM friends f1 
     WHERE f1.username = 'Thomas') 
AND f2.friendname <> 'user1' 
AND f2.friendname = 'user2';  

그것은 기본적으로 확인한다.

친구의 모든 네트워크를 통해 어떻게 확장 할 수 있는지 알아 내려고 노력하고 있습니다. 나는 내 친구의 친구가 아니라는 뜻입니다. 필요에 따라 레벨이

답변

5
SELECT * 
FROM (
     SELECT username 
     FROM friends 
     START WITH 
       username = 'myname' 
     CONNECT BY 
       friendname = PRIOR username 
       AND level <= 3 
     ) 
WHERE username = 'friendname' 
     AND rownum = 1 

업데이트 :

WITH q AS 
     (
     SELECT username, friendname 
     FROM friends 
     UNION ALL 
     SELECT friendname, username 
     FROM friends 
     ), 
     f AS 
     (
     SELECT friendname, level 
     FROM q 
     START WITH 
       username = 'Thomas' 
     CONNECT BY NOCYCLE 
       username = PRIOR friendname 
     ) 
SELECT * 
FROM f 
WHERE friendname = 'Jo' 
     AND rownum = 1 

이 질의 : 당신이 등 제 3 층의 친구

우정 관계가 대칭 인 경우를 검색 할 수 있습니다, 당신은 다음과 같은 쿼리를해야한다 테이블을 비정규 화하면 훨씬 빠르게 만들 수 있습니다. 다음과 같이 우정마다 두 개의 레코드를 저장하십시오 :

CREATE TABLE dual_friends (orestes NOT NULL, pylades NOT NULL, CONSTRAINT pk_dualfriends_op PRIMARY KEY (orestes, pylades)) ORGANIZATION INDEX 
AS 
SELECT username, friendname 
FROM friends 
UNION ALL 
SELECT friendname, username 
     FROM friends 

그런 다음 당신은 단지 dual_friends와 위의 CTE을 대체 할 수

WITH f AS 
     (
     SELECT pylades, level 
     FROM dual_friends 
     START WITH 
       orestes = 'Thomas' 
     CONNECT BY NOCYCLE 
       orestes = PRIOR pylades 
       AND level <= 3 
     ) 
SELECT * 
FROM f 
WHERE pylades = 'Jo' 
     AND rownum = 1 

, 인덱스를 사용하고 어떤 합리적인 값으로 수준을 제한 특히, 훨씬 더 효율적이 될 것이다.

+0

그러나 오라클은 그 SQL 나를 위해 일을 보인다 – Mark

+0

당신을 위해 검색 수준을 할 것입니다 그래서하여 연결 사용하여 계층 적 쿼리를 가지고 사용할 수 있습니다. 좋아, 사용자 이름이 FRIENDNAME이 테이블을 주어진 상상 토마스 앨리스 앨리스 밥 밥 조 조이 –

+0

@user 잘못 토마스 네트워크에없는 나타내는 아무것도주지 = '조'MyName로 = 토마스와 FRIENDNAME하여 해당 SQL을 실행하면 :인가 네 우정 관계는 대칭이야? 즉, '앨리스'가 '토마스'의 친구라면 '토마스'는 '앨리스'의 친구일까요? 나는 그가 존재한다고 믿지만, 그것을 지정하는 것이 더 낫다. – Quassnoi

관련 문제