[SQL] case when을 이용한 피봇팅(group by, aggregate)

hyeji·2023년 4월 21일

피봇팅(Pivotiong)

피벗팅이란 행 레벨로 만들어진 데이터를 열 레벨로 전환하는 것을 말한다.

예를 들어

YEARDEPTNOJOBEMPIDSALARY
202210SALESMAN225
202220MANAGER125
202230CLERK330
202220MANAGER110

SUM

위와 같은 데이터가 있을 때 년도별 직원의 급여를 보고자 할 때

SELECT YEAR, EMPID, SUM(SALARY) SALARY
FROM EMP
GROUP BY YEAR, EMPID

이 코드를 실행하면 아래와 같은 테이블을 볼 수 있다.

YEAREMPIDSALARY
20221100
20222200
20223300
20224400
20225500
20226600

이 때, 위 데이터를 피봇 형식으로 만들기 위해서는 아래와 같은 코드를 실행시키면 된다.

SELECT YEAR, AVG(SALARY) AVG_SAL,
	SUM(CASE WHEN EMPID = 1 THEN SALARY END) EMP_1,
	SUM(CASE WHEN EMPID = 2 THEN SALARY END) EMP_2,
	...
	SUM(CASE WHEN EMPID = N THEN SALARY END) EMP_N
# EMPID가 N일 때 SALARY를 더한 값을 EMP_N으로 지정
FROM EMP
GROUP BY YEAR

그럼 아래와 같은 결과를 볼 수 있다.

YEARAVG_SALEMP_1EMP_2EMP_N
2022300100200900
2023500200250900

이렇게 피봇 형식으로 보면 보기에는 좋지만 데이터 적으로는(?) 좋지 않다.

왜냐면 N명의 직원 데이터를 보기 위해서는 N개의 코드를 쳐야 하고, 후에 직원이 추가된다면 그만큼 또 코드가 늘어나기 때문이다.

COUNT

각 부서별 직원 수를 보고 싶을 때는 아래 코드를 사용하면 된다.

SELECT DEPTNO, COUNT(*) AS COUNT
FROM EMP
GROUP BY DEPTNO
DEPTNOCOUNT
1010
205
306

각 부서를 group by로 묶고, 직업별 사람 수를 pivot형식으로 나타내보자

SELECT DEPTNO, COUNT(CASE WHEN JOB='SALESMAN' THEN 1 END) AS SALESMAN,
	COUNT(CASE WHEN JOB='MANAGER' THEN 1 END) AS MANAGER,
	COUNT(CASE WHEN JOB='CLERK' THEN 1 END) AS CLERK
FROM EMP
GROUP BY DEPTNO

위 코드를 실행하면 아래와 같은 결과를 볼 수 있다.

DEPTNOSALESMANMANAGERCLERK
10532
203NULL2
303NULL3

이 때, 조심해야 할 점이 있는데 바로

COUNT(CASE WHEN JOB=’SALESMAN’ THEN 1 ELSE 0 END) AS SALESMAN

이렇게 코드를 쓰면 안 된다는 점이다.

THEN 1 이라 적는다고 그걸 하나씩 세라는 말이 아니다

1이 하나 라는 의미가 아님!

THEN 3, THEN 10 이렇게 적어도 결과는 위 테이블처럼 나온다.

(+3, +10이 아니라는 말)

그렇기 때문에 아래와 같은 코드를 실행하면 잘못된 결과가 나온다.

SELECT DEPTNO, COUNT(*) AS ALL,
	COUNT(CASE WHEN JOB='SALESMAN' THEN 1 ELSE 0 END) AS SALESMAN,
	COUNT(CASE WHEN JOB='MANAGER' THEN 1 ELSE 0 END) AS MANAGER,
	COUNT(CASE WHEN JOB='CLERK' THEN 1 ELSE 0 END) AS CLERK
FROM EMP
GROUP BY DEPTNO
DEPTNOALLSALESMANMANAGERCLERK
1010101010
205555
306666

각 부서 인원이 직업별로 나눠서 COUNT 되는 게 아니라 그냥 직업에 관계 없이 전체 수가 집계되는 것을 볼 수 있다.

ELSE를 사용하고 싶다면 ELSE 0 가 아닌 ELSE NULL 을 사용해야 한다.

CASE WHEN JOB=’~’ THEN 1 ELSE 0 END 를 사용하고 싶다면 COUNT가 아닌 SUM 을 이용해야 한다.

SELECT DEPTNO, COUNT(*) AS ALL,
	SUM(CASE WHEN JOB='SALESMAN' THEN 1 ELSE 0 END) AS SALESMAN,
	SUM(CASE WHEN JOB='MANAGER' THEN 1 ELSE 0 END) AS MANAGER,
	SUM(CASE WHEN JOB='CLERK' THEN 1 ELSE 0 END) AS CLERK
FROM EMP
GROUP BY DEPTNO

이렇게 적으면 맨 처음 봤던 올바른 결과를 볼 수 있음

profile
Data Analyst

0개의 댓글