그 동안 취업 준비하면서 코딩 테스트 문제를 하루에 2~3개씩 풀어보면서 한 번 틀렸거나 특별하게 풀었던 문제 정리
문제
테이블 이름:
OCCUPATIONS
컬럼:Name,Occupation
목표:
Occupation열을 피벗(pivot)하여 각 직업(Doctor, Professor, Singer, Actor)을 열(Column)로 만들고,- 각
Occupation에 해당하는 사람들의Name을 알파벳 순으로 정렬하여 세로로 나열합니다.- 이름의 수는 직업마다 다를 수 있으므로, 짧은 직업군에는 해당하지 않는 칸은
NULL로 채웁니다.- 컬럼 순서는 Doctor, Professor, Singer, Actor 순서로 고정입니다.
풀이
- CTE t에서 row_number() 사용
- 각 직업별 이름을 알파벳 순서로 정렬
- 각 이름에 번호를 부여해서, 나중에 group by
- case when 을 이용해 직업별로 하나의 컬럼 생성
- group by num
- 같은 순서에 해당하는 이름들을 하나의 행으로 묶음
- max() 사용 이유
- 각 그룹에서 case when으로 필터링된 name은 하나뿐이므로, max()를 사용해서 그 값 추출
- 만약 해당 직업에 num 순서에 사람이 없으면 null 반환
정답 쿼리
WITH
t1 as (SELECT *, row_number() over(partition by occupation order by name) as num
FROM occupations
)
SELECT
max(case when occupation = 'doctor' then name else null end),
max(case when occupation = 'professor' then name else null end),
max(case when occupation = 'singer' then name else null end),
max(case when occupation = 'actor' then name else null end)
FROM t1
GROUP BY num;
틀린 이유: 집계함수를 사용해서 그룹화된 1개의 값만을 가져오는 방법을 모르고 풀었었다
SQL은 집계함수(MAX, MIN 등)를 써야만 SELECT에서 GROUP BY 없이 컬럼을 출력할 수 있다
문제: Employee_id 당 department_id가 여려개 존재한 경우 primary_flag가 "Y"인 경우의 department_id를 추출
각 직원 아이디별로 primary 부서 아이디 추출
초반 문제 접근:
CTE 나 서브쿼리를 이용해 id가 2개 이상인 직원을 필터링해서 기존 테이블과 조인하려 했음
문제 풀이 방식:
초반 문제 접근으로 쿼리를 짜면 쿼리가 복잡해지고 메모리 낭비도 심할꺼란 생각이 들었다.
"윈도우 함수를 이용해서 primart_flag에 순위를 주면 어떨까?"라는 생각을 기반으로 정답 쿼리를 만들게 됨.
가독성 측면이나 메모리 측면에서도 더 효율적이라고 생각이 됨.
정답 쿼리
WITH t as
(SELECT employee_id, department_id, row_number() over(partition by employee_id order by primary_flag) num
FROM employee
)
SELECT employee_id, department_id
FROM t
WHERE num = 1;