Tools/- SQL

[SQL] solvesql | 세 명이 서로 친구인 관계 찾기 | self join 활용하기, on절 조건 여러개

스위민 2025. 2. 14. 11:25

문제

https://solvesql.com/problems/friend-group-of-3/

 

https://solvesql.com/problems/friend-group-of-3/

 

solvesql.com

 

문제가 좀 특이하다..!

a - b 가 친구이고
b - c 가 친구이고
c - a 가 친구인 경우를 구하면 된다


참고로 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 buser 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 시킬건지 정신을 바짝 차리고 생각해야하는 문제다.

그림을 그려보면 이해가 편하지만

쿼리 테스트에서는 그림을 그려볼 순 없으니 머릿속으로 잘 구상해야한다.