[프로그래머스/MYSQL] 언어별 개발자 분류하기

NOO·2024년 4월 4일
1

CODING TEST - SQL

목록 보기
3/5

👋😊 인사

안녕하세요! 새로 나온 SQL의 마지막 문제를 해결하려 왔습니다.
이번 문제는 꽤 많은 시간을 걸려서 푼 만큼 성취감 높았습니다ㅎㅎ

📍[Lv.4] 언어별 개발자 분류하기

🔗 문제 링크

https://school.programmers.co.kr/learn/courses/30/lessons/276036

🛠️ 문제 풀이

1. Front End 기술을 가지면서 python 능력을 가진 사람 리스트 구하기

SELECT DISTINCT(ID), FIRST_NAME, LAST_NAME, EMAIL, SKILL_CODE
FROM DEVELOPERS D, SKILLCODES S
WHERE 1 = 1
    AND (D.SKILL_CODE & S.CODE) > 0
    AND SKILL_CODE & (SELECT S.CODE FROM SKILLCODES S WHERE NAME = 'Python') > 0
    AND S.CATEGORY = 'Front End';

2. C# 개발자 구하기

SELECT DISTINCT(ID), FIRST_NAME, LAST_NAME, EMAIL, SKILL_CODE
FROM DEVELOPERS D, SKILLCODES S
WHERE 1 = 1
    AND (D.SKILL_CODE & S.CODE) > 0
    AND S.NAME = 'C#'

3. 그 외의 프론트 개발자

SELECT DISTINCT(ID), FIRST_NAME, LAST_NAME, EMAIL, SKILL_CODE
FROM DEVELOPERS D, SKILLCODES S
WHERE 1 = 1
    AND (D.SKILL_CODE & S.CODE) > 0
    AND S.CATEGORY = 'Front End';

4. CASE WHEN 구문을 통해 GRADE 표시
(1) A에 해당하는 개발자들 A로 표시하기

SELECT CASE WHEN ID IN ( SELECT DISTINCT(ID) 
                        FROM DEVELOPERS D, SKILLCODES S 
                        WHERE (D.SKILL_CODE & S.CODE) > 0
                            AND SKILL_CODE & (SELECT S.CODE FROM SKILLCODES S WHERE NAME = 'Python') > 0
                            AND S.CATEGORY = 'Front End'
                        ) THEN 'A'
            ELSE 'F' END GRADE
        ,ID
        ,EMAIL
FROM DEVELOPERS D;

(2) C랑 합쳐서 표시하고 UNION을 통해 B랑 합치기

원래는 아래와 같이 코드를 짰었으나...

(SELECT CASE WHEN ID IN ( SELECT DISTINCT(ID) 
                        FROM DEVELOPERS D, SKILLCODES S 
                        WHERE (D.SKILL_CODE & S.CODE) > 0
                            AND SKILL_CODE & (SELECT S.CODE FROM SKILLCODES S WHERE NAME = 'Python') > 0
                            AND S.CATEGORY = 'Front End'
                        ) THEN 'A'
            ELSE 'C' END GRADE
        ,ID
        ,EMAIL
FROM DEVELOPERS D, SKILLCODES S
WHERE (D.SKILL_CODE & S.CODE) > 0
    AND S.CATEGORY = 'Front End'
GROUP BY ID, EMAIL)
UNION
(SELECT 'B' GRADE
        ,ID
        ,EMAIL
FROM DEVELOPERS D, SKILLCODES S
WHERE 1 = 1
    AND (D.SKILL_CODE & S.CODE) > 0
    AND S.NAME = 'C#'
GROUP BY ID, EMAIL)
ORDER BY GRADE, ID;

실패해서 분석해보니, 아마 C#+Front End 기술이 있으면 C로 분류되는 것 같았습니다.
그래서

(3) A,B,C 모두 하나의 SELECT 절에서 CASE WHEN으로 구분

WITH TMP AS (
    SELECT CASE WHEN ID IN ( SELECT DISTINCT(ID) 
                             FROM DEVELOPERS D, SKILLCODES S 
                             WHERE (D.SKILL_CODE & S.CODE) > 0
                                AND SKILL_CODE & (SELECT S.CODE FROM SKILLCODES S WHERE NAME = 'Python') > 0
                                AND S.CATEGORY = 'Front End'
                             GROUP BY ID
                           ) THEN 'A'
                WHEN ID IN ( SELECT DISTINCT(ID)
                             FROM DEVELOPERS D, SKILLCODES S 
                             WHERE (D.SKILL_CODE & S.CODE) > 0
                                AND S.NAME = 'C#'
                             GROUP BY ID
                           ) THEN 'B'
                WHEN ID IN ( SELECT DISTINCT(ID)
                             FROM DEVELOPERS D, SKILLCODES S 
                             WHERE (D.SKILL_CODE & S.CODE) > 0
                                AND S.CATEGORY = 'Front End'
                             GROUP BY ID
                           ) THEN 'C'
            END GRADE
        ,ID
        ,EMAIL
    FROM DEVELOPERS D
    GROUP BY ID, EMAIL
)
SELECT *
FROM TMP
WHERE GRADE IS NOT NULL
ORDER BY GRADE, ID;

👾 소스 코드

WITH TMP AS (
    SELECT CASE WHEN ID IN ( SELECT DISTINCT(ID) 
                             FROM DEVELOPERS D, SKILLCODES S 
                             WHERE (D.SKILL_CODE & S.CODE) > 0
                                AND SKILL_CODE & (SELECT S.CODE FROM SKILLCODES S WHERE NAME = 'Python') > 0
                                AND S.CATEGORY = 'Front End'
                             GROUP BY ID
                           ) THEN 'A'
                WHEN ID IN ( SELECT DISTINCT(ID)
                             FROM DEVELOPERS D, SKILLCODES S 
                             WHERE (D.SKILL_CODE & S.CODE) > 0
                                AND S.NAME = 'C#'
                             GROUP BY ID
                           ) THEN 'B'
                WHEN ID IN ( SELECT DISTINCT(ID)
                             FROM DEVELOPERS D, SKILLCODES S 
                             WHERE (D.SKILL_CODE & S.CODE) > 0
                                AND S.CATEGORY = 'Front End'
                             GROUP BY ID
                           ) THEN 'C'
            END GRADE
        ,ID
        ,EMAIL
    FROM DEVELOPERS D
    GROUP BY ID, EMAIL
)
SELECT *
FROM TMP
WHERE GRADE IS NOT NULL
ORDER BY GRADE, ID;

🌅 마무리

🤔 어떤 문제가 있었나요?

집합연산자인 UNION을 통해 B를 합치려고 했으나 C#+Front End 기술이 있으면 C로 분류되는 문제가 발생했습니다.

🤔 어떻게 해결했고 무엇을 알았나요?

집합연산자 대신 스칼라 서브쿼리와 임시테이블을 사용해서 다르게 접근하여 풀었습니다.

👋😊 인사

부족한 글 읽어주셔서 감사합니다.
잘못된 부분 혹은 개선할만한 부분에 대한 댓글 항상 환영합니다.

profile
ᐕ) ⁾⁾

0개의 댓글