홈 › SQL 고급 › 05 / 10

행과 열 바꾸기

PIVOT, UNPIVOT, 조건부 집계
섹션 6진행 0 / 10

2. 핵심 원리

2.1 조건부 집계로 하는 피벗

피벗은 세 단계로 이해합니다.

  1. 열로 만들 기준(분기)마다 CASE WHEN qtr = n THEN amt END 를 만듭니다. 조건이 맞지 않으면 NULL 입니다.
  2. 그 식을 SUM 으로 감쌉니다. SUM 은 NULL 을 건너뛰므로 해당 분기 금액만 남습니다.
  3. 행으로 남길 기준(사원)으로 GROUP BY 합니다.

해당 분기 행이 하나도 없으면 SUM 이 NULL 을 돌려주므로 칸이 비어 보입니다. 이 성질은 3절에서 COALESCE 로 다룹니다.

핵심

피벗은 "열마다 CASE 하나, 감싸는 집계 하나, GROUP BY 하나" 입니다. 열의 개수와 값은 쿼리에 미리 적혀 있어야 합니다.

2.2 PIVOT 과 UNPIVOT 문법

전용 문법은 같은 구조를 짧게 씁니다.

항목 Oracle MSSQL MySQL
PIVOT 11g 부터 2005 부터 없음
UNPIVOT 11g 부터 2005 부터 없음
UNPIVOT 의 NULL 기본 제외 늘 제외 -
NULL 포함 옵션 INCLUDE NULLS 없음 -
열→행 다른 방법 UNION ALL CROSS APPLY (VALUES ...) UNION ALL

PIVOT 은 집계 함수, 값이 들어 있던 열, 새 열 이름 목록을 받습니다. UNPIVOT 은 값이 들어갈 열 이름, 옛 열 이름이 들어갈 열 이름, 펼칠 열 목록을 받습니다. Tibero 는 Oracle 호환이지만 PIVOT 을 쓰기 전에 사용 중인 버전의 지원 여부를 확인합니다.

2.3 정적 열 목록의 한계

PIVOT 의 IN (...) 목록은 값을 미리 적어야 하는 정적 목록입니다. 조건부 집계도 열마다 CASE 를 적으므로 마찬가지입니다. 분기는 1~4 로 고정이라 문제가 없지만, 고객사 이름처럼 값이 늘고 줄면 열 목록을 자동으로 만들 수 없습니다.

이런 경우는 값 목록을 먼저 조회해 문자열로 이어 붙여 쿼리 문장을 만들고 실행하는 동적 SQL 로 처리합니다. Oracle 에는 값 목록을 ANY 로 받는 PIVOT XML 도 있지만, 결과가 XML 한 칸이라 여기서는 언급만 합니다. 열 개수가 바뀌는 보고서는 SQL 이 아니라 화면·보고서 도구에서 돌리는 편이 대개 단순합니다.