solvesql
- 친구 수 집계하기
👉 문제 바로가기(solvesql)
-- 데이터베이스에 포함된 모든 사용자에 대해 각 사용자의 친구 수를 집계해 출력
WITH tmp_t AS (
SELECT
user_id,
SUM(num_friends) as num_friends
FROM
(SELECT user_a_id as user_id, COUNT(DISTINCT user_b_id) as num_friends
FROM edges
GROUP BY user_a_id
UNION ALL
SELECT user_b_id as user_id, COUNT(DISTINCT user_a_id) as num_friends
FROM edges
GROUP BY user_b_id)
GROUP BY
user_id
)
SELECT
t1.user_id,
CASE
WHEN t2.num_friends IS NULL THEN 0
ELSE t2.num_friends
END as num_friends
FROM
users t1
LEFT JOIN
tmp_t t2 ON t1.user_id = t2.user_id
ORDER BY
t2.num_friends DESC, t1.user_id
[ 논리 과정 ]
- user_a_id와 user_b_id의 페어가 unique 한지 확인
- user_a_id 기준 그룹핑하여 친구 수 집계
- user_b_id 기준 그룹핑하여 친구 수 집계
- 친구 수 집계한 두 테이블 합치기
- 최종 결과 조회하기
[ 문제 상황 ]
- 오답 부분 코드
-- 오답 부분 코드
WITH tmp_t AS (
SELECT
user_id,
SUM(num_friends) as num_friends
FROM
(SELECT user_a_id as user_id, COUNT(DISTINCT user_b_id) as num_friends
FROM edges
GROUP BY user_a_id
UNION
SELECT user_b_id as user_id, COUNT(DISTINCT user_a_id) as num_friends
FROM edges
GROUP BY user_b_id)
GROUP BY
user_id
)
- 각 user_a_id, user_b_id 기준으로 친구 수 집계하여 합쳐서 조회해도 결과가 정답과 다르게 조회됨
[ 해결 ]
- 개수가 다르게 나왔던 원인은 UNION 이었음.
- UNION으로 합칠 시, 값이 동일한 데이터의 중복을 제거하고 합쳐지기 때문에 데이터 누수 발생
- UNION ALL을 통해 1차적으로 합쳐서 데이터 누수 없이 친구 수를 집계하고 user_id로 그룹핑
[ 회고 ]
- 데이터를 조회해봤을 때, 눈에 데이터 누수가 보이지 않는다고 해서 데이터 누수가 발생하지 않은 것이 아니다.
- 데이터를 병합하거나 분할하거나 조건을 걸어 조회할 때, 해당 쿼리가 원하는 결과를 조회하는데 작은 오류라도 발생시키지 않는지 꼼꼼하게 체크해야한다.
- UNION과 UNION ALL의 차이는 중복 제거 여부이다. 중복 제거와 같이 데이터의 변형을 일으킬 수 있는 요소들을 꼼꼼하게 점검해야한다.
'DA Study > TIL' 카테고리의 다른 글
[TIL] 윈도우 함수를 활용한 누적합 구하기 #SQL #SQLite #solvesql (0) | 2025.02.24 |
---|---|
[TIL] Null값과 연산하기 - COALESCE()활용 #SQL #SQLite #solvesql (0) | 2025.02.23 |
[TIL] CASE WHEN 구문으로 PIVOT 테이블 만들기 #SQL #SQLite #solvesql (0) | 2025.02.20 |
[TIL] 문자열 슬라이싱, 문자열 나눠서 조회하기 #SQL #SQLite #solvesql (4) | 2025.02.17 |
[TIL] 집계함수 중복처리(DISTINCT) #SQL #SQLite #solvesql (0) | 2025.02.13 |