참고로 a - b 인 행이 존재하면 b - a 인 행은 없다. 즉, 중복 행은 존재하지 않는다.
코드
나의 답안
with user_3 as (select
a.user_a_id,
a.user_b_id,
case when
a.user_b_id = b.user_a_id then b.user_b_id
end as user_c_id
from edges a
join edges b
on a.user_b_id = b.user_a_id)
select *
from user_3
where ((user_a_id, user_c_id) in (select user_a_id, user_b_id from edges))
and ((user_a_id = 3820) or (user_b_id = 3820) or (user_c_id = 3820))
-- 20분 성공 ..!
좀 더 깔쌈한 타 블로그 답안
SELECT
A.user_a_id "user_a_id"
, B.user_a_id "user_b_id"
, B.user_b_id "user_c_id"
FROM
edges A
JOIN edges B ON A.user_b_id = B.user_a_id
JOIN edges C ON A.user_a_id = C.user_a_id AND B.user_b_id = C.user_b_id
WHERE
A.user_a_id = 3820
OR B.user_a_id = 3820
OR B.user_b_id = 3820
문제 풀이
이 문제의 핵심은 self join을 적절하게 사용하는 것이다.
💡 나의 답안 풀이
1. self join을 활용해서 user a / user b / user c를 구한다. 여기에서 user a - b 는 친구 / user b - c 는 친구이다.
2. user a - c 가 친구인 경우를 where절에서 in 연산자를 사용해서 구한다.
3. user a / b / c 중 id가 3820인 것을 구한다.
💡 타 블로그 답안 풀이
나의 답안은 임시 테이블에서 user a / b / c를 구하고 다시 select 문의 where절에서 user a - c가 친구인지 확인했다. 그러나 타 풀이 방법을 보면 self join에서 on에 조건을 걸어서 user a - c가 친구인 경우를 구한다. 테이블의 관계 구조를 그려보면 이렇게 구성되어 있는 걸 볼 수 있다.
1번에서 user a / b / c를 구한다. self join을 활용해서 b 테이블의 user b가 user c가 된 것이다.
2번에서 user a - c가 친구인지 확인하기 위해 c 테이블의 user a - b과 self join 시킨다. 여기에서 on에 조건을 두개 사용해서 구할 수 있겠다.
on에 조건을 두개 거는 건 생소해서 자주 사용해봐야겠다.
join에서 on으로 조건 걸기
on절에서 조건을 여러개 걸 수 있다.
테이블의 관계 구조를 정의하는 용도로도 사용할 수 있지만 (ex. A.user_id = B.user_id)
where절처럼 사용할 수도 있다. (ex. B.user_id = '3820')
느낀 점
무슨 테이블의 user a와 user b를 어떻게 self join 시킬건지 정신을 바짝 차리고 생각해야하는 문제다.