Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
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
Archives
Today
Total
관리 메뉴

집 짓는 개발블로그

[프로그래머스] 조건에 맞는 개발자 찾기 (MySQL) - EXISTS, 서브쿼리 본문

MySQL

[프로그래머스] 조건에 맞는 개발자 찾기 (MySQL) - EXISTS, 서브쿼리

취준er 2024. 6. 22. 18:21

 

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

 

프로그래머스

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

programmers.co.kr

문제 요약: DEVELOPERS 테이블에서 SKILLS_CODE 컬럼의 값(INT)이, (SKILLCODES 테이블에서 NAME컬럼의 값이 'Python'과 'C#' 중 하나인 레코드들)의 CODE 컬럼의 값(INT)을 포함하는 레코드들을 select하면 된다. 논리 연산자 &나 |을 써서 포함관계를 판단할 수 있다.

 

 

소요시간: 17분

열심히 헤맸다.

 

 

 

포인트

1. MySQL의 쿼리 실행 순서

2. 서브쿼리에 대하여

 

 

 

정답

-- SKILL_CODE & CODE = CODE면 해당 개발자가 해당 스킬 가진 것

WITH WANTED_SKILLS AS(
    SELECT CODE
    FROM SKILLCODES
    WHERE NAME IN ('Python', 'C#')
)
-- 서브쿼리 안에서 FROM D 바로 썼더니(메인쿼리의 별칭 바로 썼더니) 실패 (1146, "Table 'programmers.d' doesn't exist") 에러남
SELECT ID, EMAIL, FIRST_NAME, LAST_NAME
FROM DEVELOPERS D 
-- EXISTS는 메인쿼리부터 접근하니까, 일단 D테이블의 한 데이터를 딱 잡음
-- 그 뒤에 서브쿼리 접근해서, 이 D테이블의 데이터의 SKILL_CODE와, WS테이블의 모든 CODE를 매칭해가면서 비교하고
-- WHERE조건을 만족하는 CODE가 있으면? (= 이 개발자가 파이썬이나 C# 갖고 있으면) EXISTS 조건이 TRUE
-- -> 이러한 개발자들의 데이터를 출력
WHERE EXISTS (SELECT * FROM WANTED_SKILLS WS WHERE D.SKILL_CODE & WS.CODE = WS.CODE)
ORDER BY ID;

 

 

일단 어제 공부한 EXISTS로 풀고 나서 여러 가지 시도해봤다. SQL 문제를 풀 때마다 아래와 같은 잘못된 풀이들로 대충 풀어버리고 싶은 충동이 샘솟는데 하나씩 실행해보고 왜 안 되는지를 확실히 알아두기 위함이다. 

 

 

실패한 풀이 1

WITH WANTED_SKILLS AS(
    SELECT CODE
    FROM SKILLCODES
    WHERE NAME IN ('Python', 'C#')
)

SELECT ID, EMAIL, FIRST_NAME, LAST_NAME
FROM DEVELOPERS D
WHERE D.SKILL_CODE & WANTED_SKILLS.CODE = WANTED_SKILLS.CODE
ORDER BY ID;

실패 (1054, "Unknown column 'WANTED_SKILLS.CODE' in 'where clause'")

이러면 메인쿼리에서 내가 만든 WANTED_SKILLS를 못 찾는다. 

 

 

 

그래서 이렇게도 해봤다. 서브쿼리를 그냥 그 자리에 갖다넣어봤다.

 

실패한 풀이 2

SELECT ID, EMAIL, FIRST_NAME, LAST_NAME
FROM DEVELOPERS D
WHERE D.SKILL_CODE & (SELECT CODE
    FROM SKILLCODES
    WHERE NAME IN ('Python', 'C#')) = (SELECT CODE
    FROM SKILLCODES
    WHERE NAME IN ('Python', 'C#'))
ORDER BY ID;

실패 (1242, 'Subquery returns more than 1 row')

당연한 결과 감사합니다.

 

 

 

 

실험이 끝났으니 이제 공부하자.

 

 

 

1. MySQL의 쿼리 접근 순서

 

기본적으로 FROM - WHERE - GROUP BY - HAVING - SELECT - ORDER BY [ - LIMIT] 순서대로 실행된다.

따라서 GROUP BY 뒤에 어떤 컬럼명을 써서 해당 컬럼으로 데이터를 그룹핑했다면, 반드시 SELECT 뒤에도 해당 컬럼명을 써줘야 한다! 

(코테에서는 별칭 위치가 헷갈리면 그냥 별칭을 안 쓰는 방향으로 타협본다. 🫠)

 

 

 

 

2. 서브쿼리

 

 

🔥서브쿼리 사용 시 주의점🔥

1) 서브쿼리에는 ; 를 붙이지 않는다

2) 서브쿼리 → 메인쿼리 순서대로 실행된다.

3) 2번 때문에 헷갈릴 수 있는데, 서브쿼리는 메인쿼리의 컬럼을 사용할 수 있다. 메인쿼리는 서브쿼리 거 못 쓴다. 

 

 

서브쿼리는 3가지가 있다.

 

(1) 스칼라 서브쿼리(Scala Subquery)

 

- SELECT 뒤에 쓰이는 서브쿼리

- 다른 테이블에서 '값 하나'만 가져올 때 주로 사용.

SELECT M.GENDER, (SELECT MAX(ID) FROM OTHER_TABLE WHERE GENDER = M.GENDER) AS 'SUB'
FROM MAIN_TABLE M

- 반드시 한 번에 하나의 레코드만 리턴해야 함!

- 위 예시에서는 '"M의 GENDER컬럼의 어떤 값와 GENDER컬럼의 값이 일치"하는 OTHER_TABLE의 레코드들 中' ID의 최댓값 하나씩을 뽑아 SELECT한다. 

- 일치하는 데이터가 없으면 NULL 이 나온다.

 

M.GENDER SUB
Female 32
Male 40
Etc  

위와 같은 형태의 결과가 나올 것이다. 맨 마지막은 NULL이다. 

 

 

(2) 인라인 뷰(Inline View)

 

- FROM 뒤에 쓰이는 서브쿼리

- FROM 뒤에 서브쿼리를 사용한다면 반드시 [AS] '__' 으로 Alias를 붙여줘야 한다. 🔥

06/27/24 수정 - 작은따옴표 붙이면 에러 난다. 큰따옴표 붙여도 에러 난다. 그냥 [AS] SUB 이렇게 해줘야 한다! 

 

 

(3) 중첩 서브쿼리(Nested Subquery)

 

- WHERE 뒤에 쓰이는 서브쿼리

- SELECT된 레코드가 딱 하나면 WHERE절에서 바로 비교 연산자 뒤에 써도 된다. 하나가 아니라면, all 또는 any로 전체를 감싸서 쓸 수도 있다. (예시: WHERE MAIN.AGE > ALL(SELECT AGE FROM SUB_TABLE) ) 

 

 

 

 

다 공부하고 나서 다른 방법으로 풀어보려고 시도했는데 실패함. 조인하기엔 컬럼이 없다. 나중에 돌아와서 다시 생각해봐야겠다.