본문 바로가기

SQL - Mysql & Oracle/SQL 실전 코딩 테스트

[MySQL & Oracle]HackerRank - Occupations 해설 및 오답노트

반응형

오늘은 Hacker Rank 중에서 The Report 문제에 대한 간단한 번역과 해답에 대해서 요약하고자 한다. 해설은 MySQL과 Oracle에서 모두 작동하는 것으로 기록했고, 문제 풀이 과정에서 얻었던 내용을 오답노트로 기록하였다.

 

목차

1. 문제 출처 및 소개

2. Full Join을 활용한 Orcale 풀이

3. GROUP BY를 활용한 MySQL 풀이

 

 

1. 문제 출처 및 소개

 

  • 문제의 출처: Hacker Rank The Report
  • 문제의 요구 사항 정리
    • 요구사항 1. 각 직업별로 알파벳 순서대로 이름을 나열
    • 요구사항 2. 만약 순서에 맞는 사람이 없다면 NULL로 호출
    • 요구사항 3. Column의 순서는 doctor, professor, singer 그리고 actor이 되어야 할 것

 

사실 이 문제를 해결할 때 요구사항 2번을 어떻게 효율적으로 대처하느냐에 따라 문제 풀이의 당락이 결정된다. 초반에는 굉장히 많이 고생을 했지만, MySQL 환경에서 Groupby를 통해서 해결하였고, 다른 문제 풀이 접근 방식으로 Oracle에서 Full Join 방식으로 해결할 수 있었다. 지금부터 어떻게 해결했는지 자세하게 코드를 공유하겠다. 

Occupation 문제의 요구 사항 해석
해커랭크 occupation 요구 사항

 

 

 

 

 

2. Full Join을 활용한 Orcale 풀이

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
SELECT t1.d_name
    , t2.p_name
    , t3.s_name
    , t4.a_name
FROM (
    SELECT row_number() OVER (ORDER BY a.Name) as num
        , a.Name AS d_name
    FROM Occupations a
    WHERE a.Occupation = 'Doctor'
) t1
FULL JOIN (
    SELECT row_number() OVER (ORDER BY b.Name) as num
        , b.Name AS p_name
    FROM Occupations b
    WHERE b.Occupation = 'Professor'
) t2 ON t1.num = t2.num
FULL JOIN (
    SELECT row_number() OVER (ORDER BY c.Name) as num
        , c.Name AS s_name
    FROM Occupations c
    WHERE c.Occupation = 'Singer'
    ) t3 ON t2.num = t3.num
FULL JOIN (
    SELECT row_number() OVER (ORDER BY d.Name) as num
        , d.Name AS a_name
    FROM Occupations d
    WHERE d.Occupation = 'Actor'
    ) t4 ON t3.num = t4.num
;
 
cs

 

이 답을 보기 전에 Full Join에 대해서 잘 모르는 사람이 있다면, 이전 포스팅을 참고하길 바란다. 문제 풀이 공략은 다음과 같다. 각 직업별로 알파벳 순서대로 이름을 정렬한 다음에 임의의 row_number를 부여한다. 그 이후 이 row_number을 key값으로 두어 4개의 Group을 Join해주면 정답이 호출되는 방식을 채택하였다. 

 

하지만 이 문제 풀이 방식은 리소스를 상대적으로 많이 쓴다는 단점이 있다. 왜냐하면 동일한 Table을 4번 불러내어 전처리를 해야 하고, 이후에 JOIN 함수가 들어가기 때문에 이상적인 풀이 방식이라고 보기에는 다소 힘들 수 있다. 장점으로는 row_number와 full join이라는 함수를 연습해 보기 좋은 문제였다고 생각한다. 

 

 

 

 

3. GROUP BY 를 활용한 MySQL 풀이

  •  
1
2
3
4
5
6
7
8
9
10
11
12
13
 
SELECT 
    , MIN(CASE WHEN t1.occupation = 'DOCTOR'      THEN name ELSE NULL END) 
    , MIN(CASE WHEN t1.occupation = 'PROFESSOR'   THEN name ELSE NULL END) 
    , MIN(CASE WHEN t1.occupation = 'SINGER'      THEN name ELSE NULL END) 
    , MIN(CASE WHEN t1.occupation = 'ACTOR'       THEN name ELSE NULL END)
FROM (
    SELECT occupation
    , name
    , ROW_NUMBER() OVER (PARTITION BY occupation ORDER BY name) AS f_num
    FROM OCCUPATIONS
    ) AS t1
GROUP BY f_num
cs

 

이 문제 풀이의 공략은 아래와 같다. 우선은 전체적으로 직업에 따라 row_number를 생성해 주고 정렬 기준은 알파벳 순으로 맞춘다. 그 이후 CASE WHEN문을 통해서 각각의 직업이 조회되는 이름만 불러오고 이외는 NULL을 호출한다. 이때 row_number로 Groupby를 해주게 되면 Min함수든 Max함수든 이름을 우선적으로 불러오기 때문에 문제의 요구사항을 만족할 수 있게 되는 논리이다. 

 

이 문제 풀이 방식은 위의 문제 풀이 방식보다 리소스를 절약할 수 있다는 차원과 코드의 길이가 불필요하게 길어지지 않는다는 장점이 있기 때문에 최종적으로는 이런 문제 풀이 방식을 지향해야 할 것이다. 하지만 사실 난도가 있는 문제 풀이 방식이라는 단점도 있기 때문에 비슷한 유형을 만났을 때 생각이 나지 않는다면 위의 방식이라도 채택해야 할 것이다. 

반응형