-- requester_id + accepter_id = friends number
-- id, num
WITH id_num AS (
SELECT requester_id as id,
COUNT(*) as num
FROM RequestAccepted
GROUP BY requester_id
UNION
SELECT accepter_id as id,
COUNT(*) as num
FROM RequestAccepted
GROUP BY accepter_id
)
-- SELECT * FROM id_num
SELECT id, sum(num) as num
FROM id_num
GROUP BY id
ORDER BY num desc
LIMIT 1
CTE에서 requester_id로 그룹화한 테이블과 accepter_id로 그룹화한 테이블에 레코드가 {id:17, num:5}가 각각 있는데 UNION 한 뒤에 id로 그룹화하면 id:17, num:10이 되는 게 아니라 id:17, num:5가 되는 것을 확인할 수 있다.
UNION 연산자의 중복 제거 때문인데, UNION 연산자는 중복을 허용하지 않기 때문에 중복을 제거하고 하나만 남긴다. 중복을 허용하고 그대로 유지하고 싶다면 UNION ALL 연산자를 사용해야 한다.
쿼리 최적화를 진행할 때, 중복이 없을 때 UNION ALL을 사용해서 진행하다 보니 이 부분에서 혼동이 왔었다.
CTE를 작성할 때, 그룹화를 해서 집계 함수를 사용할 필요 없이 id만 출력되도록 테이블을 만들고 본 쿼리에서 그룹화하여 세는 게 가장 빠른 쿼리다.
WITH id_num AS (
SELECT requester_id as id
FROM RequestAccepted
UNION ALL
SELECT accepter_id as id
FROM RequestAccepted
)
SELECT id, COUNT(*) as num
FROM id_num
GROUP BY 1
ORDER BY 2 desc
LIMIT 1