DataBase
[SolveSQL/Advent of SQL 2024] 세 명이 서로 친구인 관계 찾기
MKJo
2024. 12. 26. 13:06
문제:
https://solvesql.com/problems/friend-group-of-3/
처음엔 간단(?)해 보였지만 하면 할수록 점점 이상한 결과들이 나오기 시작했다..
셀프 조인을 2~3번씩 걸면서 조건을 이렇게 저렇게 주고 해봤는데 원하는 결과가 나오지않아서 결국 야매스러운 방법으로 해결했다..

1. Edges 테이블의 USER_A_ID 혹은 USER_B_ID가 3820인 행찾기
2. 3820의 친구목록을 하나의 컬럼으로 묶어주기
WITH UserFriends AS (
SELECT
CASE WHEN User_A_Id = 3820 THEN USER_B_ID
ELSE User_A_Id
END as Friend
FROM Edges
WHERE 3820 IN (user_a_id, user_b_id)
)
3. [3820의 친구목록] 중 Edges테이블의 [user_a_id, user_b_id] 두 컬럼 모두에 해당하는 행을 찾은 후 작은수, 큰수로 정렬하여 중복제거 [1, 2], [2, 1]과 같은 조합이 있을 수 있으므로..
ex) 3820의 친구목록이 1,2,3,4 라면 Edges 테이블의 [user_a_id, user_b_id] 조합이 [1,2,3,4]에서 조합되는 녀석
FriendPairs AS (
SELECT DISTINCT
CASE
WHEN E.user_a_id < E.user_b_id THEN E.user_a_id
ELSE E.user_b_id
END as user_a_id,
CASE
WHEN E.user_a_id < E.user_b_id THEN E.user_b_id
ELSE E.user_a_id
END as user_b_id
FROM Edges E
INNER JOIN UserFriends UF1 ON E.user_a_id = UF1.Friend
INNER JOIN UserFriends UF2 ON E.user_b_id = UF2.Friend
)
풀고나서 알았는데 Edges컬럼의 user_a_id < user_b_id는 항상 참이다. 즉 위의 CASE구문없이 user_a_id, user_b_id만 조회 했어도 됐음
중간결과
이제 위 user_a_id, user_b_id 사이에 A < B < C 순으로 3820을 끼워넣으면 된다.
어떻게할까 고민좀 하긴 했는데.. 그냥 무식하게 CASE로 때려박았다..
4. 최종결과
WITH UserFriends AS (
-- 3820 유저의 모든 친구
SELECT
CASE WHEN User_A_Id = 3820 THEN USER_B_ID
ELSE User_A_Id
END as Friend
FROM Edges
WHERE
3820 IN (user_a_id, user_b_id)
),
FriendPairs AS (
-- 3820 유저의 친구들 쌍
SELECT DISTINCT
CASE
WHEN E.user_a_id < E.user_b_id THEN E.user_a_id
ELSE E.user_b_id
END as user_a_id,
CASE
WHEN E.user_a_id < E.user_b_id THEN E.user_b_id
ELSE E.user_a_id
END as user_b_id
FROM Edges E
INNER JOIN UserFriends UF1 ON E.user_a_id = UF1.Friend
INNER JOIN UserFriends UF2 ON E.user_b_id = UF2.Friend
)
SELECT
CASE WHEN USER_A_ID < 3820 AND USER_B_ID < 3820 THEN USER_A_ID -- [3820]이 가장 큰 경우
WHEN USER_A_ID < 3820 THEN USER_A_ID -- [3820]이 중간인 경우
ELSE 3820 -- [3820]이 가장 작은 경우
END as user_a_id,
CASE WHEN USER_A_ID < 3820 AND USER_B_ID < 3820 THEN USER_B_ID
WHEN USER_A_ID < 3820 THEN 3820
ELSE USER_A_ID
END as user_b_id,
CASE WHEN USER_A_ID < 3820 AND USER_B_ID < 3820 THEN 3820
WHEN USER_A_ID < 3820 THEN USER_B_ID
ELSE USER_B_ID
END as user_c_id
FROM
FriendPairs
참으로 무식한 결과다.. ㅎㅎ
하지만 통과^^