Algorithm/Programmers SQL

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

제우제우 2024. 9. 18. 16:21

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

코딩테스트 연습 > GROUP BY > 언어별 개발자 분류하기

 

문제 분석

난이도: LEVEL4

 

문제 요구사항

DEVELOPERS 테이블에서 GRADE별 개발자의 정보를 조회하려 합니다. GRADE는 다음과 같이 정해집니다.

A : Front End 스킬과 Python 스킬을 함께 가지고 있는 개발자
B : C# 스킬을 가진 개발자
C : 그 외의 Front End 개발자
GRADE가 존재하는 개발자의 GRADE, ID, EMAIL을 조회하는 SQL 문을 작성해 주세요.

결과는 GRADE와 ID를 기준으로 오름차순 정렬해 주세요.

정답 코드1

WITH FrontEnd AS ( -- SKILLCODES FrontEnd select
    SELECT CODE 
    FROM SKILLCODES
    WHERE CATEGORY = 'Front End'
),
C AS ( -- SKILLCODES C# select
    SELECT CODE 
    FROM SKILLCODES
    WHERE NAME = 'C#'
),
Python AS ( -- SKILLCODES Python select
    SELECT CODE 
    FROM SKILLCODES
    WHERE NAME = 'Python'
),
GRADE AS ( -- GRADE 
    SELECT ID, 
    CASE 
        WHEN SKILL_CODE & (SELECT CODE FROM Python) >= 1 AND (SELECT COUNT(*)
                                                              FROM FrontEnd
                                                              WHERE SKILL_CODE & CODE >= 1
                                                              ) >= 1 THEN 'A' 
        WHEN SKILL_CODE & (SELECT CODE FROM C) >= 1 THEN 'B'
        WHEN (SELECT COUNT(*)
              FROM FrontEnd
              WHERE SKILL_CODE & CODE >= 1
              ) >= 1 THEN 'C' 
        ELSE  'D'
    END GRADE 
    FROM DEVELOPERS 
)
SELECT G.GRADE, G.ID, D.EMAIL
FROM GRADE G JOIN DEVELOPERS D
ON G.ID = D.ID 
WHERE G.GRADE != 'D'
ORDER BY 1, 2

 

SKILLCORDES 테이블에서 

각 기술스택에 대한 코드를 CTE로 뽑는다. 

  • FrontEnd: (JavaScript, React, Vue) 
  • C: C#
  • Python: Python

GRADE CTE 

CASE WHEN THEN을 사용하여 문제에서 요구하는 A,B,C로 등급을 나누고 A,B,C에 해당하지 않는 개발자는 D등급 부여 

 

GRADE CTE, DEVELOPERS 테이블을 조인하여 

등급이 D인 개발자는 거르고 GRADE, ID, EMAIL 정보 출력 

정렬은 GRADE, ID 오름차순 순서대로 

 

문제점 

CASE WHEN THEN에서 FrontEnd Code를 찾는 쿼리가 2번씩 사용된다. 물론 'A' 등급이거나 'B' 등급인 사람은 1번 실행

정답코드2에서 개선 

 

정답 코드2

WITH FrontEnd AS ( -- SKILLCODES FrontEnd select
    SELECT CODE 
    FROM SKILLCODES
    WHERE CATEGORY = 'Front End'
),
C AS ( -- SKILLCODES C# select
    SELECT CODE 
    FROM SKILLCODES
    WHERE NAME = 'C#'
),
Python AS ( -- SKILLCODES Python select
    SELECT CODE 
    FROM SKILLCODES
    WHERE NAME = 'Python'
),
GRADE AS ( -- GRADE 
    SELECT ID, 
    CASE 
        WHEN FRONT_COUNT >= 1 AND SKILL_CODE & (SELECT * FROM Python) >= 1 THEN 'A'
        WHEN SKILL_CODE & (SELECT * FROM C) >= 1 THEN 'B'
        WHEN FRONT_COUNT >= 1 THEN 'C'
        ELSE 'D'
    END GRADE 
    FROM (SELECT ID, (SELECT COUNT(*) 
                      FROM FrontEnd
                      WHERE SKILL_CODE & CODE >= 1
                     ) FRONT_COUNT, SKILL_CODE 
          FROM DEVELOPERS
         ) DEVELOPERS_UPGRADE 
)
SELECT G.GRADE, G.ID, D.EMAIL
FROM GRADE G JOIN DEVELOPERS D
ON G.ID = D.ID 
WHERE G.GRADE != 'D'
ORDER BY 1, 2

 

FrontEnd CTE를 보면 3개의 결과가 나오는데 

해당 결과를 합쳐서 단일 결과로 반환해도 괜찮다. 

이유 각 코드는 2의 제곱수이고 이진수 & 계산을 하기 때문에 

정답 코드3: FrontEnd CTE SUM(CODE) 적용 & GRADE CTE 없이 바로 JOIN 사용 

정답 코드3

WITH FrontEnd AS ( -- SKILLCODES FrontEnd select
    SELECT SUM(CODE) CODE 
    FROM SKILLCODES
    WHERE CATEGORY = 'Front End'
),
C AS ( -- SKILLCODES C# select
    SELECT CODE 
    FROM SKILLCODES
    WHERE NAME = 'C#'
),
Python AS ( -- SKILLCODES Python select
    SELECT CODE 
    FROM SKILLCODES
    WHERE NAME = 'Python'
)
SELECT 
CASE 
    WHEN D.SKILL_CODE & F.CODE >= 1 AND D.SKILL_CODE & P.CODE >= 1 THEN 'A' 
    WHEN D.SKILL_CODE & C.CODE >= 1 THEN 'B'
    WHEN D.SKILL_CODE & F.CODE >= 1 THEN 'C'
END GRADE, ID, EMAIL
FROM DEVELOPERS D, FrontEnd F, C AS C, Python P 
HAVING GRADE IS NOT NULL 
ORDER BY 1, 2