SQL/문제풀이

[HackerRank] Occupations 📌

응엉잉 2024. 5. 11. 16:07

https://www.hackerrank.com/challenges/occupations/problem?isFullScreen=false

occupation별로 column이 있는 형태 --> CASE문을 이용해서 기본 골자를 만드는 문제이지 않을까 했다

SELECT CASE WHEN occupation = 'Doctor' THEN name END AS Doctor,
    CASE WHEN occupation = 'Professor' THEN name END AS Professor,
    CASE WHEN occupation = 'Singer' THEN name END AS Singer,
    CASE WHEN occupation = 'Actor' THEN name END AS Actor
FROM occupations o

 

그치만 이렇게 하면 조건을 만족하지 않는 모든 row에 대해 NULL값이 떠버린다.

이런 상황을 만들지 않기 위해서 ROW_NUMBER()를 사용해줘야 한다!

 

ROW_NUMBER()는 특정 조건에 따라 행을 고유하게 식별하고, 순서를 정렬해야 할 때 자주 사용된다.

이 문제에서는 occupation별로 행을 고유하게 식별하고, 이름에 따라 정렬을 해줘야 했기에 ROW_NUMBER()를 사용하는 아이디어를 얻을 수 있다.

SELECT ROW_NUMBER() OVER(PARTITION BY occupation ORDER BY name) AS ord,
    occupation,
    name
FROM occupations

위 쿼리를 실행하면 다음과 같은 결과가 나온다.

이 실행 결과를 테이블처럼 따로 빼서 사용하기 위해 WITH 문을 사용한다

 

WITH sub AS (SELECT ROW_NUMBER() OVER(PARTITION BY Occupation ORDER BY name) ord,
    Occupation,
    name
FROM Occupations)

SELECT
    MAX(CASE WHEN occupation = 'Doctor' THEN name ELSE NULL END) AS Doctor,
    MAX(CASE WHEN occupation = 'Professor' THEN name ELSE NULL END) AS Professor,
    MAX(CASE WHEN occupation = 'Singer' THEN name ELSE NULL END) AS Singer,
    MAX(CASE WHEN occupation = 'Actor' THEN name ELSE NULL END) AS Actor
FROM sub
GROUP BY ord
ORDER BY ord

 

우선 ord에 따라 GROUP BY를 해줘야 한다.

위의 with절을 ord에 따라 order by 하면 다음과 같은 결과가 나오는데,

group by를 통해 각 ord에 따라서 row를 구성하고 + CASE문을 통해 각 occupation별로 이름을 넣어주면 된다

이때 아무 집계함수 (min, max)를 사용해서 null값을 무시해주면 된다!

 

GROUP BY에 사용한 column을 꼭 SELECT문에 사용해야 한다고 생각했는데, 몇가지 예외 case가 있었다.

이 문제에서는 각 직업별로 동일한 행에 이름을 정렬하기 위해 GROUP BY를 사용한다.

ex. 각 직업의 첫번째 이름은 첫번째 행에, 두번째 이름은 두번째 행에 ...

이런 식으로 그룹화 기준으로만 사용되고, 결과 집합에서는 볼 필요가 없으므로 SELECT문에 사용하지 않는다.

 

 

사실 이 문제를 아직 완전히 이해하진 못했다 ..

일단 배운 점은

 

1. ROW_NUMBER()의 활용

column별로 식별이 필요한 경우 사용하면 좋다

 

2. GROUP BY의 활용

각 직업별로 동일한 행에 이름을 정렬하기 위해 사용