https://school.programmers.co.kr/learn/courses/30/lessons/276036
Level 4 문제답게 조금 복잡한 문제다.
단계적으로 접근해보자.
우선 GRADE를 다음과 같이 나눠야한다.
이 중 Front End 스킬은 SKILLCODES 테이블에서 CATEGORY 컬럼이 Frond End 인 것들의 CODE 값이다.
CODE 값은 2의 거듭제곱 꼴이므로 비트연산이나 합연산을 통해서 구할 수 있다.
예를들어 JavaScript 의 CODE 가 16,
React 의 CODE 가 2048 이면
16 + 2048 = 2064, 16 | 2048 = 2064 이다.
찾아보니 집계 함수에 SUM() 뿐만아니라 BIT_OR() 이라는 함수도 있었다.
우선 현재까지의 결과를 한 테이블에 담는다.
WITH FE AS (
SELECT SUM(CODE) AS SKILL_CODE
-- SELECT BIT_OR(CODE) AS SKILL_CODE 도 가능
FROM SKILLCODES
GROUP BY CATEGORY
HAVING CATEGORY = 'Front End'
)
-- FE.SKILL_CODE 에는 Front End 기술을 모두 표현해놓은 값이 들어있음
이제 위 결과를 가지고 'A', 'B', 'C'에 해당하는 결과를 출력하자.
SELECT
CASE
WHEN DEV.SKILL_CODE & FE.SKILL_CODE
AND DEV.SKILL_CODE & (SELECT CODE FROM SKILLCODES WHERE NAME = 'Python')
THEN 'A'
WHEN DEV.SKILL_CODE & (SELECT CODE FROM SKILLCODES WHERE NAME = 'C#')
THEN 'B'
WHEN DEV.SKILL_CODE & FE.SKILL_CODE
THEN 'C'
ELSE NULL
END AS GRADE
, ID
, EMAIL
FROM
DEVELOPERS DEV
, FE
문제는 그 다음이다.
GRADE 가 없는 사람은 표현하면 안된다.
결국 위 테이블을 한번 더 읽으면서 WHERE 절에서 IS NOT NULL 을 통해 필터링을 해야한다.
(이 부분은 최적의 솔루션이 아닐 수도 있다.)
가독성을 위해 WITH 절에 추가하고자 했는데,
WITH 절에 여러개를 적용하는 방법은
WITH A AS ()
WITH B AS ()
가 아닌
WITH A AS (), B AS ()
이런 식이다.
위 내용을 바탕으로 최종 코드를 작성하면 된다.
WITH FE AS (
SELECT BIT_OR(CODE) AS SKILL_CODE
FROM SKILLCODES
GROUP BY CATEGORY
HAVING CATEGORY = 'Front End'
), DEV_GRADE AS (
SELECT
CASE
WHEN DEV.SKILL_CODE & FE.SKILL_CODE
AND DEV.SKILL_CODE & (SELECT CODE FROM SKILLCODES WHERE NAME = 'Python')
THEN 'A'
WHEN DEV.SKILL_CODE & (SELECT CODE FROM SKILLCODES WHERE NAME = 'C#')
THEN 'B'
WHEN DEV.SKILL_CODE & FE.SKILL_CODE
THEN 'C'
ELSE NULL
END AS GRADE
, ID
, EMAIL
FROM
DEVELOPERS DEV
, FE
)
SELECT
GRADE
, ID
, EMAIL
FROM
DEV_GRADE
WHERE
GRADE IS NOT NULL
ORDER BY
GRADE, ID
더 좋은 해결방법이 있다면 언제든 댓글로 알려주세요 🤗