[SQL문제풀기] 언어별 개발자 구하기

silver's avatar
Jan 12, 2025
[SQL문제풀기] 언어별 개발자 구하기

문제

MYSQL

방법

내가 작성한 정답 1

WITH A AS ((SELECT D.ID, D.EMAIL FROM DEVELOPERS D JOIN SKILLCODES S ON D.SKILL_CODE & S.CODE != 0 WHERE S.NAME = 'Python' GROUP BY D.ID, D.EMAIL) INTERSECT (SELECT D.ID, D.EMAIL FROM DEVELOPERS D JOIN SKILLCODES S ON D.SKILL_CODE & S.CODE != 0 WHERE S.CATEGORY = 'Front End' GROUP BY D.ID, D.EMAIL)), B AS (SELECT D.ID, D.EMAIL FROM DEVELOPERS D JOIN SKILLCODES S ON D.SKILL_CODE & S.CODE != 0 WHERE S.NAME = 'C#' ), C AS (SELECT D.ID, D.EMAIL FROM DEVELOPERS D JOIN SKILLCODES S ON D.SKILL_CODE & S.CODE != 0 WHERE (D.ID, D.EMAIL) NOT IN (SELECT * FROM A) AND (D.ID, D.EMAIL) NOT IN (SELECT * FROM B) AND S.CATEGORY = 'Front End'), D AS (SELECT CASE WHEN (ID, EMAIL) IN (SELECT * FROM A) THEN 'A' WHEN (ID, EMAIL) IN (SELECT * FROM B) THEN 'B' WHEN (ID, EMAIL) IN (SELECT * FROM C) THEN 'C' END AS GRADE, ID, EMAIL FROM DEVELOPERS ) SELECT * FROM D WHERE GRADE IS NOT NULL ORDER BY GRADE ASC, ID ASC
 
 
그룹을 나눠서 풀이 도중 전체적인 쿼리가 너무 길어져서 찾은

방법2

내가 작성한 오답

WITH A AS (SELECT D.ID, D.EMAIL, A.CATEGORY, A.NAME FROM DEVELOPERS D JOIN SKILLCODES A ON D.SKILL_CODE & A.CODE != 0) , TB AS ( SELECT CASE WHEN F.ID = P.ID THEN 'A' WHEN D.ID = C.ID THEN 'B' WHEN F.ID NOT IN (P.ID,C.ID) THEN 'C' END AS GRADE, D.ID, D.EMAIL FROM DEVELOPERS D JOIN A P ON P.NAME = 'Python' JOIN A C ON C.NAME = 'C#' JOIN A F ON F.CATEGORY = 'Front End' ) SELECT GRADE, ID, EMAIL FROM TB GROUP BY GRADE,ID,EMAIL ORDER BY GRADE ASC, ID ASC
JOIN A P ON P.NAME = 'Python'와 JOIN A C ON C.NAME = 'C#'각 개발자가 여러 스킬을 가질 수 있기 때문에, 이렇게 여러번 중복해서 조인하면 중복 결과가 발생했다.
WITH A AS (SELECT D.ID, D.EMAIL, A.CATEGORY, A.NAME FROM DEVELOPERS D JOIN SKILLCODES A ON D.SKILL_CODE & A.CODE != 0) SELECT P.ID ,P.EMAIL, P.NAME FROM DEVELOPERS D JOIN A P ON P.NAME = 'Python' JOIN A C ON C.NAME = 'C#' JOIN A F ON F.CATEGORY = 'Front End'
notion image

내가 작성한 오답 2

: 시간초과로 인한 오답! 시간이 더 지나도 맞는 쿼리가 아닐 수도 있다.
WITH SKILL AS (SELECT * FROM DEVELOPERS D JOIN SKILLCODES A ON D.SKILL_CODE & A.CODE != 0) , TB AS ( SELECT CASE WHEN D.SKILL_CODE & P.CODE != 0 THEN 'A' WHEN D.SKILL_CODE & C.CODE != 0 THEN 'B' WHEN D.SKILL_CODE & F.CODE != 0 AND F.ID NOT IN (P.ID,C.ID) THEN 'C' END AS GRADE, D.ID, D.EMAIL FROM DEVELOPERS D JOIN SKILL P ON P.NAME = 'Python' JOIN SKILL C ON C.NAME = 'C#' JOIN SKILL F ON F.CATEGORY = 'Front End' ) SELECT GRADE, ID, EMAIL FROM TB WHERE GRADE IS NOT NULL GROUP BY GRADE,ID,EMAIL ORDER BY GRADE ASC, ID ASC
notion image

내가 작성한 정답 2

시간 초과의 원인이 될 수 있는 것들
  1. 많은 join문
  1. not in 에서 연산할 것이 많으면 시간이 오래 걸릴 수 있다.
 
WITH TB AS ( SELECT D.ID, D.EMAIL, CASE WHEN P.NAME IS NOT NULL AND F.NAME IS NOT NULL THEN 'A' WHEN C.NAME IS NOT NULL THEN 'B' WHEN F.NAME IS NOT NULL THEN 'C' END AS GRADE FROM DEVELOPERS D LEFT JOIN SKILLCODES P ON P.NAME = 'Python' AND D.SKILL_CODE & P.CODE != 0 LEFT JOIN SKILLCODES C ON C.NAME = 'C#' AND D.SKILL_CODE & C.CODE != 0 LEFT JOIN SKILLCODES F ON F.CATEGORY = 'Front End' AND D.SKILL_CODE & F.CODE != 0 ) SELECT GRADE, ID, EMAIL FROM TB WHERE GRADE IS NOT NULL GROUP BY GRADE, ID, EMAIL ORDER BY GRADE ASC, ID ASC
  • 성능향상을 위해 cte쿼리 하나를 삭제하고 join문에 조건을 추가했다.
  • join문 작성 시 left join을 사용해 조건에 맞지 않는 record들도 결과값에 넣고 나중에 걸러낸다.
  • case 조건문에 join해서 온 row들에서 각각의 조건들이 없다면 제외시키기 위해 NOT NULL을 조건으로 걸어줬다. 이 때 P.NAME, C.NAME, F.NAME들은 가져온 조건들에 만족하기 못하는 경우를 걸러내기 위한 것이기 때문에 NAME은 SKILLCODES에 존재하는 CATEGORY나 CODE로 변경이 가능하다.
 
💡
D.SKILL_CODE & P.CODE != 0 조건은 아래 다른 문제 참고
 

다른 사람들이 작성한 정답

SELECT CASE WHEN GROUP_CONCAT(B.NAME) LIKE ("%Python%") AND GROUP_CONCAT(B.CATEGORY) LIKE("%Front%") THEN "A" WHEN GROUP_CONCAT(B.NAME) LIKE ("%C#%") THEN "B" WHEN GROUP_CONCAT(B.CATEGORY) LIKE ("%Front%") THEN "C" END AS GRADE , A.ID, A.EMAIL FROM DEVELOPERS AS A JOIN SKILLCODES AS B ON (A.SKILL_CODE & B.CODE = B.CODE) GROUP BY ID,EMAIL HAVING GRADE IS NOT NULL ORDER BY GRADE ASC , ID ASC
💡
GROUP_CONCAT(B.NAME): 현재 그룹에 속한 모든 스킬 이름을 쉼표로 구분하여 하나의 문자열로 결합한다.
notion image
notion image
→ LIKE는 문자열이 특정 패턴을 포함하는지를 확인하여 false면 0으로 true면 1로 표현한다.
 
Share article

silver