https://leetcode.com/problems/article-views-i/description/?envType=study-plan-v2&envId=top-sql-50
코드설명
DISTINCT + EXISTS + GROUP BY 를 활용합니다.
이 문제의 경우, 단번에 DISTINCT를 활용하거나, GROUP BY 를 활용해서 중복제거를 한다고 생각할 것 입니다.
중복레코드를 제거할 목적으로 DISTINCT 연산자를 사용할 경우의 단점은 무엇일까요?
단점은, 조건에 해당하는 데이터를 모두 읽어서 중복을 제거해야 합니다. 부분범위 처리는 당연히 불가하고, 모든 데이터를 읽는 과정에서 많은 I/O가 발생합니다.
그렇기에 총 3가지 방식으로 작성해보았습니다.
1. DISTINCT
2. GROUP BY
3. DISTINCT + EXISTS Nested Subquery --> Eixsts Subquery가 맞다면 바로 subquery 탐색이 종료되긴 하지만, DISTINCT로 인해 부분범위처리는 작동하지 않습니다. 즉, 모든 결과를 모은 후 중복제거한 후 처리한다는 의미입니다. 만약 DISTINCT가 없었다면, VIEWS 테이블에 대한 부분범위처리 원리를 적용할 수 있습니다.
MYSQL 코드
DISTINCT를 활용한 정답코드1입니다.
SELECT DISTINCT(AUTHOR_ID) AS ID
FROM VIEWS
WHERE AUTHOR_ID = VIEWER_ID
ORDER BY ID ASC;
GROUP BY 를 활용한 정답코드2입니다.
SELECT AUTHOR_ID AS ID
FROM VIEWS
WHERE AUTHOR_ID = VIEWER_ID
GROUP BY AUTHOR_ID
ORDER BY ID ASC;
3.EXISTS를 활용하여 최대한 작은 데이터를 읽는 정답코드3입니다.
이렇게 처리하면, EXISTS 서브쿼리가 데이터 존재여부만 확인하면 되기에, 조건절을 만족하는 테이블을 모두 읽지 않는다고 생각할 수 있지만, DISTINCT가 사용되어 여전히 부분범위 처리가 불가합니다.
SELECT DISTINCT V.AUTHOR_ID as id
FROM VIEWS V
WHERE EXISTS ( SELECT 'X' FROM VIEWS V2 WHERE V2.VIEWER_ID = V.AUTHOR_ID AND V2.ARTICLE_ID = V.ARTICLE_ID)
ORDER BY V.AUTHOR_ID;