함께 아는 친구가 많은 순으로 조회하기 0 7 2,484

by 창조의날개 [2016.02.15 14:51:06]


 

뭔가 상큼한 방법이 있지 않을가 싶어 질문 올려봅니다.

 

아래와 같은 데이터가 있습니다.

WITH TT(ID, F_ID, STATUS) AS(
    SELECT 'AAA','BBB',2 FROM DUAL UNION ALL
    SELECT 'AAA','CCC',2 FROM DUAL UNION ALL
    SELECT 'DDD','AAA',2 FROM DUAL UNION ALL
    SELECT 'BBB','CCC',2 FROM DUAL UNION ALL
    SELECT 'DDD','CCC',2 FROM DUAL UNION ALL
    SELECT 'DDD','GGG',0 FROM DUAL UNION ALL
    SELECT 'DDD','FFF',2 FROM DUAL
)

 

ID를 기준으로 친구 신청한 F_ID가 있습니다.

 

신청하면 STATUS는 0이 되고, 거절하면 1이 되고 승락하면 2가 됩니다.

 

그래서 친구가 된 ID를 기준으로 함께 아는 친구가 많은 친구 아이디순으로 조회 하려 합니다.

 

내 아이디가 'AAA'라고 가정하고 아래처럼 결과가 나올 것으로 예상합니다.

 

ID       CNT

CCC        2

BBB         1

DDD        1

FFF          1

 

나의 친구는 BBB, CCC, DDD 입니다.

그러므로 CCC는 BBB, DDD와 함께 친구로 2가 됩니다.

BBB는 CCC와 함께 친구로 1

DDD는 CCC와 함께 친구로 1 

FFF는 DDD와 함께 친구로 1 

 

 

감사합니다.

 

 

by jkson [2016.02.15 17:13:26]

상큼하진 않지만

눈에 보이는대로 기술하였습니다;

상큼한 답변은 다음 분이..

  SELECT ID, COUNT (1) cnt
    FROM (SELECT DECODE (a.ID, b.ID, b.f_id, b.ID) ID
            FROM (SELECT DISTINCT DECODE (ID, :ID, f_id, ID) ID
                    FROM tt
                   WHERE (ID = :ID OR f_id = :ID)
                     AND status = '2') a
               , tt b
           WHERE (   a.ID = b.ID
                  OR a.ID = b.f_id)
             AND b.status = '2'
             AND b.ID != :ID
             AND b.f_id != :ID)
   GROUP BY ID
   ORDER BY cnt DESC, ID

 


by 창조의날개 [2016.02.15 17:28:28]

저는 이렇게 해봤는데..

상큼하지 않아서...


SELECT AA.ID, COUNT(*) CNT
FROM (
      SELECT ID, F_ID FROM TT WHERE STATUS = 2
      UNION ALL
      SELECT F_ID ID, ID F_ID FROM TT WHERE STATUS = 2
     ) AA
  , (
      SELECT CASE WHEN ID = 'AAA' THEN F_ID
                  WHEN F_ID = 'AAA' THEN ID
             END F_ID
      FROM TT
      WHERE STATUS = 2
        AND (ID = 'AAA' OR F_ID = 'AAA')
    ) BB
WHERE AA.F_ID = BB.F_ID
  AND AA.ID != 'AAA'
GROUP BY ID
ORDER BY CNT DESC, ID
;

 


by jkson [2016.02.15 17:33:50]

비슷한 방식이네요ㅋ

뭔가 멋진 쿼리를 만들어주실 분이 계실 것만 같은 느낌적인 느낌이 옵니다.


by 창조의날개 [2016.02.16 08:48:01]

그렇죠.. 뭔가 있을거 같기는 한데..

딱히 방법이 떠오르지 않아 올려 봤어요..

 


by 마농 [2016.02.16 09:16:22]
SELECT f_id
     , COUNT(*) cnt
  FROM (SELECT id, f_id FROM tt WHERE status = 2
         UNION
        SELECT f_id, id FROM tt WHERE status = 2
        )
 WHERE LEVEL = 2
   AND f_id != CONNECT_BY_ROOT(id)
 START WITH id = 'AAA'
 CONNECT BY NOCYCLE PRIOR f_id = id
 GROUP BY f_id
 ORDER BY cnt DESC, f_id
;

 


by 창조의날개 [2016.02.16 10:09:21]

막연하게 CONNECT BY를 생각해보기 했는데..

역시 마농님이 깔끔하게 해주시네요..


by jkson [2016.02.16 10:18:41]
CONNECT BY NOCYCLE, CONNECT_BY_ROOT, LEVEL 지정까지 비슷하게 만들다가
결과가 영 이상하게 나와서 포기했는데 역시 상큼한 답변을 달아주시는군요ㅎㅎ
어제 만든 거 보니 무슨 생각으로 만들었는지 level = 3으로 해놨네요ㅎㅎ
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입