SQL

[SQL/solvesql LV3] 초기 사용자의 친구 관계 찾기

jy9892 2025. 12. 22. 21:08
반응형

https://solvesql.com/problems/friendship-between-early-users/

https://solvesql.com/problems/friendship-between-early-users/

solvesql.com

 
Facebook 소셜 네트워크 데이터베이스에는 사용자의 정보와 사용자 사이의 친구 관계가 저장되어 있습니다.

edges 테이블의 각 행은 두 사용자(user_a_id, user_b_id)가 서로 친구 관계라는 의미입니다.
 
이 데이터베이스에서 사용자 ID는 auto increment 정수로 생성되기 때문에, ID가 낮을수록 더 일찍 가입한 사용자라고 볼 수 있습니다.
 
따라서 친구 관계인 두 사용자 ID의 합(user_a_id + user_b_id)이 작을수록 더 초창기에 형성된 친구 관계일 가능성이 높다고 추측할 수 있습니다.
 

🎯 문제 정리

테이블: edges
주요 컬럼

  • user_a_id : 친구 관계 사용자 A의 ID
  • user_b_id : 친구 관계 사용자 B의 ID

찾고 싶은 값

  • 전체 친구 관계 중에서
    두 사용자 ID의 합(id_sum)이 “상위 0.1%”에 해당하는 모든 친구 관계

출력 컬럼

  • user_a_id
  • user_b_id
  • id_sum (= user_a_id + user_b_id)

 

🎯 문제 해결 흐름

친구 관계 한 줄을 기준으로, 우리는 다음을 계산해야 합니다.

  1. 각 친구 관계의 id_sum 계산 (id_sum = user_a_id + user_b_id)
  2. id_sum이 작은 순서대로 정렬해서 “초기일수록 앞쪽”에 오게 한다.
  3. 그 정렬 결과에서 각 관계의 순위(rn) 를 만든다. (가장 초기 관계가 1등, 다음이 2등 …)
  4. 전체 친구 관계 수(total_cnt)를 구한다.
  5. 문제에서 정의한 “상위 %”는 아래와 같다.
    • 상위 % = 순위 / 전체 관계 수
    • 따라서 “초기 0.1%”는 rn / total_cnt <= 0.001
    • 이 조건을 만족하는 친구 관계만 출력하면 된다.

 

🎯쿼리

WITH ranked AS (
  SELECT
    user_a_id,
    user_b_id,
    (user_a_id + user_b_id) AS id_sum,
    ROW_NUMBER() OVER (ORDER BY (user_a_id + user_b_id) ASC) AS rn,
    COUNT(*) OVER () AS total_cnt
  FROM edges
)
SELECT
  user_a_id,
  user_b_id,
  id_sum
FROM ranked
WHERE rn / total_cnt <= 0.001
ORDER BY id_sum ASC, user_a_id, user_b_id

 

🎯 핵심 문법 설명

1) ROW_NUMBER() — 정렬된 결과에 “번호표(순위)” 붙이기

 
ROW_NUMBER() OVER (ORDER BY id_sum ASC)
  • ORDER BY id_sum ASC 기준으로 줄 세운 뒤
  • 각 행에 1, 2, 3… 번호를 붙입니다.
  • 즉, rn은 id_sum이 작은 순서 기준 몇 번째인지(순위)를 의미합니다.


이 문제에서는 “초기 친구 관계”를 찾으므로
id_sum이 작은 관계가 앞 순위가 되도록 ASC를 사용합니다.

2) COUNT(*) OVER() — 전체 행 개수를 모든 행에 붙이기

 
COUNT(*) OVER ()
  • edges 테이블 전체 행 수(=전체 친구 관계 수)를
  • 각 행마다 동일하게 붙입니다.
  • 즉, total_cnt는 “전체 관계 수”입니다.


3) “상위 0.1%” 조건 구현

문제에서 정의한 상위 %:

상위 % = 순위 / 전체 관계 수

이를 그대로 SQL로 쓰면:

 
WHERE rn / total_cnt <= 0.001
  • 0.001 = 0.1%
  • “초기 0.1%”에 해당하는 관계만 필터링 됩니다.

 

이 문제는 단순한 SELECT가 아니라 윈도우 함수의 진짜 쓰임새, 순위 기반 퍼센트 필터링 등을 한 번에 보여주는 좋은 문제 입니다.
 
특히 ROW_NUMBER + COUNT(*) OVER 조합은 익혀둡시다!!!!

반응형