현재 선택한 SQL 과정

SQLP 이론 학습

이론 목록으로 돌아가기

PIVOT·UNPIVOT: 행과 열 전환

집계된 행을 열로 펼치는 PIVOT과 열을 행으로 되돌리는 UNPIVOT의 결과 구조를 익힌다.

예상 읽기 6

핵심 요약

집계된 행을 열로 펼치는 PIVOT과 열을 행으로 되돌리는 UNPIVOT의 결과 구조를 익힌다.

핵심 질문

  1. PIVOT·UNPIVOT: 행과 열 전환에서 반드시 구분해야 할 개념과 결과 규칙은 무엇인가?
  2. 0건·1건·여러 건과 NULL·동점·중복 데이터에서 결과가 어떻게 달라지는가?
  3. 비슷해 보이는 문법과 결과가 같아지는 조건, 달라지는 조건은 무엇인가?
  4. 작은 샘플 데이터를 이용해 결과를 실수 없이 예측하는 순서는 무엇인가?

학습 목표

  • PIVOT의 집계·기준·출력값 역할을 구분한다.
  • UNPIVOT의 NULL 포함 여부를 설명한다.

개념 지도

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
원본 행 단위 확인 → 집계·열 값 지정 → 행↔열 변환 → NULL·중복 검증

핵심 내용

PIVOT은 행의 분류값을 컬럼으로 바꾸면서 집계한다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT *
FROM (
  SELECT deptno, job, sal FROM emp
)
PIVOT (
  SUM(sal) FOR job IN (
    'CLERK' AS clerk,
    'MANAGER' AS manager
  )
);

집계식과 FOR 대상이 아닌 나머지 컬럼은 암묵적인 그룹 기준이 된다. 원본 인라인 뷰에 불필요한 컬럼을 넣으면 예상보다 세분된 행이 생길 수 있다.

UNPIVOT은 여러 컬럼을 이름·값 행으로 변환한다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT *
FROM sales
UNPIVOT INCLUDE NULLS (
  amount FOR quarter IN (q1 AS 'Q1', q2 AS 'Q2')
);

기본 UNPIVOT은 입력값이 NULL인 행을 제외하며 INCLUDE NULLS로 포함할 수 있다.

흔한 오해와 주의점

  • PIVOT은 단순한 행·열 모양 변경만이 아니라 집계를 포함한다.
  • IN 목록에 없는 분류값은 정적 PIVOT 컬럼으로 나오지 않는다.
  • 인라인 뷰의 남은 컬럼이 암묵적 GROUP BY 기준이 됨을 놓치지 않는다.

PIVOT·UNPIVOT 판정 순서

PIVOT 문제는 먼저 집계할 값, 열로 바꿀 구분값, 행으로 남을 그룹 기준을 나눈다. PIVOT (SUM(금액) FOR 분기 IN ('1Q' AS Q1, '2Q' AS Q2))에서 금액은 집계 대상, 분기는 열 전환 기준이며, 입력 집합에 남은 다른 컬럼은 암묵적인 GROUP BY 기준이 된다. 불필요한 컬럼이 입력 집합에 남으면 예상보다 행이 여러 개로 나뉠 수 있으므로 PIVOT 전에 필요한 컬럼만 선택한다.

UNPIVOT (금액 FOR 분기 IN (Q1 AS '1Q', Q2 AS '2Q'))는 여러 열을 이름·값 행으로 되돌린다. 기본 동작에서는 값이 NULL인 행이 제외될 수 있고, 보존해야 한다면 INCLUDE NULLS를 명시한다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT 상품ID, 분기, 금액
FROM 분기매출
UNPIVOT INCLUDE NULLS (
  금액 FOR 분기 IN (Q1 AS '1Q', Q2 AS '2Q')
);

PIVOT을 지원하지 않는 DBMS에서는 조건부 집계로 같은 결과를 만들 수 있다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT 상품ID,
       SUM(CASE WHEN 분기 = '1Q' THEN 금액 END) AS Q1,
       SUM(CASE WHEN 분기 = '2Q' THEN 금액 END) AS Q2
FROM 매출
GROUP BY 상품ID;

시험에서는 PIVOT의 FOR가 열로 전환할 값을, IN이 생성할 열 목록을 지정한다는 점과 UNPIVOT이 원본 값을 복원하는 역연산이 아니라 열을 행 구조로 재표현하는 연산이라는 점을 구분한다.

PIVOT 전후의 행 단위

원본이 다음과 같다고 가정한다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
DEPT  QUARTER  AMOUNT
10    Q1       100
10    Q2       150
20    Q1       200
SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT *
FROM sales
PIVOT (
  SUM(amount)
  FOR quarter IN ('Q1' AS q1, 'Q2' AS q2)
);
CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
DEPT  Q1   Q2
10    100  150
20    200  NULL

PIVOT에 명시하지 않은 Column은 암묵적 GROUP BY 기준이 된다. 원본에 같은 부서·분기 행이 여러 건이면 집계 함수가 필요하며, 원하지 않는 Column이 남으면 그룹이 더 잘게 나뉠 수 있다.

UNPIVOT

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT dept, quarter, amount
FROM quarterly_sales
UNPIVOT INCLUDE NULLS (
  amount FOR quarter IN (q1 AS 'Q1', q2 AS 'Q2')
);

기본 UNPIVOT은 NULL 값을 제외할 수 있으므로 INCLUDE NULLSEXCLUDE NULLS의 결과 차이를 확인한다.

조건부 집계 대안

고정된 소수 열은 SUM(CASE WHEN quarter='Q1' THEN amount END)로도 표현할 수 있다. Dynamic Column 수가 필요한 보고서는 SQL 구조 자체가 변하므로 Dynamic SQL이나 Application Rendering을 검토한다. PIVOT은 표시 구조를 바꾸는 기능이지 결과 정렬을 보장하지 않으므로 ORDER BY를 별도로 작성한다.


결과를 검증하는 순서

  1. 각 Query Block이 만드는 한 행의 의미를 먼저 적습니다.
  2. 조건을 적용하기 전 원본 행과 적용 후 남는 행을 작은 표로 그립니다.
  3. NULL 비교가 TRUE, FALSE, UNKNOWN 중 무엇인지 구분합니다.
  4. 중복 제거, 그룹화, 정렬과 행 제한이 적용되는 순서를 확인합니다.
  5. 데이터가 0건·1건·여러 건일 때도 같은 규칙이 성립하는지 검증합니다.

실무와 시험에서 함께 확인할 항목

  • ORDER BY가 없다면 결과 순서를 가정하지 않습니다.
  • 문자열·숫자·날짜 비교에서는 데이터 타입과 명시적 형변환을 확인합니다.
  • 같은 결과처럼 보이는 SQL도 NULL과 중복이 있을 때 달라질 수 있습니다.
  • 문법을 외우기 전에 샘플 데이터 3~5행으로 결과를 직접 계산합니다.

마지막 점검

  • 작성 순서가 아니라 SQL의 논리적 처리 순서로 결과를 계산합니다.
  • NULL을 0이나 빈 값과 같은 것으로 취급하지 않습니다.
  • ORDER BY가 없는 결과 순서와 DISTINCT 없는 중복 제거를 가정하지 않습니다.
  • 비슷한 문법은 0건·다건·NULL 데이터를 넣어 결과가 정말 같은지 확인합니다.

복습 문제

  1. PIVOT 결과 행이 예상보다 많을 때 먼저 확인할 컬럼은?
  2. UNPIVOT이 기본적으로 제외하는 값은?
  3. 샘플 데이터 3행으로 결과를 직접 계산할 수 있는가?
  4. NULL이 포함될 때 결과가 달라지는 지점은 어디인가?