Notice
Recent Posts
Recent Comments
Link
CHHB stroy
SQL Server PIVOT과 UNPIVOT 완벽 정리 본문
한 줄 요약
- PIVOT: 행(Row)을 열(Column)로 변환
- UNPIVOT: 열(Column)을 행(Row)으로 변환
서로 정반대 방향의 변환이다.
PIVOT — 행을 열로 회전
언제 쓰는가?
월별 매출 데이터가 행으로 12줄 쌓여 있는데, 한 줄에 1월~12월 컬럼으로 보고 싶을 때 사용한다.
변환 전 (행 기반)
| TEAM | MONTH | AMOUNT |
|---|---|---|
| 영업1팀 | 1 | 1000 |
| 영업1팀 | 2 | 2000 |
| 영업1팀 | 3 | 1500 |
변환 후 (열 기반)
| TEAM | 1월 | 2월 | 3월 |
|---|---|---|---|
| 영업1팀 | 1000 | 2000 | 1500 |
문법
SELECT *
FROM 원본테이블
PIVOT (
집계함수(값컬럼)
FOR 회전할컬럼 IN ([값1], [값2], [값3], ...)
) AS P
실전 예제
-- 팀별 월매출이 행으로 저장된 테이블
SELECT TEAM, [1] AS M01, [2] AS M02, [3] AS M03,
[4] AS M04, [5] AS M05, [6] AS M06,
[7] AS M07, [8] AS M08, [9] AS M09,
[10] AS M10, [11] AS M11, [12] AS M12
FROM (
SELECT TEAM, GOAL_MONTH, GOAL_AMOUNT
FROM TSZM_GOAL_AMT
WHERE GOAL_YEAR = '2026'
) AS SRC
PIVOT (
SUM(GOAL_AMOUNT)
FOR GOAL_MONTH IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
) AS P
핵심 포인트
집계함수는 필수다. SUM, MAX, COUNT 등을 써야 한다.IN안의 값은 하드코딩해야 한다. 동적으로 하려면 동적 SQL이 필요하다.- PIVOT 결과에서 값이 없는 셀은
NULL이 된다.ISNULL로 0 처리하면 된다.
UNPIVOT — 열을 행으로 회전
언제 쓰는가?
M01~M12 컬럼으로 저장된 데이터를 월별 행으로 풀어서 INSERT하거나 비교할 때 사용한다.
변환 전 (열 기반)
| TEAM | M01 | M02 | M03 |
|---|---|---|---|
| 영업1팀 | 1000 | 2000 | 1500 |
변환 후 (행 기반)
| TEAM | MONTH_COL | AMOUNT |
|---|---|---|
| 영업1팀 | M01 | 1000 |
| 영업1팀 | M02 | 2000 |
| 영업1팀 | M03 | 1500 |
문법
SELECT *
FROM 원본테이블
UNPIVOT (
값을담을컬럼 FOR 컬럼명을담을컬럼 IN ([컬럼1], [컬럼2], [컬럼3], ...)
) AS U
실전 예제
-- M01~M12 컬럼을 월별 행으로 변환
SELECT
TEAM_CODE,
REPLACE(MONTH_COL, 'M', '') AS GOAL_MONTH,
GOAL_AMOUNT
FROM #COLS
UNPIVOT (
GOAL_AMOUNT FOR MONTH_COL IN (M01,M02,M03,M04,M05,M06,M07,M08,M09,M10,M11,M12)
) AS U
핵심 포인트
- UNPIVOT 대상 컬럼들은 데이터 타입이 동일해야 한다. 하나라도 다르면 에러가 난다.
NULL값이 있는 행은 자동으로 제외된다. NULL도 포함하려면 미리ISNULL로 기본값을 채워야 한다.MONTH_COL에는 컬럼명이 문자열로 들어온다. 위 예제처럼REPLACE로 가공해서 사용할 수 있다.
PIVOT vs UNPIVOT 비교
| 구분 | PIVOT | UNPIVOT |
|---|---|---|
| 방향 | 행 → 열 | 열 → 행 |
| 필수 요소 | 집계함수 (SUM, MAX 등) | 없음 |
| NULL 처리 | NULL로 채워짐 | NULL 행 자동 제외 |
| 주 용도 | 리포트, 크로스탭 조회 | 데이터 정규화, MERGE용 변환 |
| IN 절 | 변환될 값 나열 | 변환할 컬럼명 나열 |
실무 활용 패턴
PIVOT: 월별 실적 리포트
-- 팀별 월별 매출을 한 줄로 조회
SELECT DEPT_CODE,
ISNULL([1], 0) AS [1월],
ISNULL([2], 0) AS [2월],
ISNULL([3], 0) AS [3월]
-- ... 12월까지
FROM (
SELECT DEPT_CODE, GOAL_MONTH, GOAL_AMOUNT
FROM TSZM_GOAL_AMT
WHERE GOAL_YEAR = '2026'
) SRC
PIVOT (
SUM(GOAL_AMOUNT) FOR GOAL_MONTH IN ([1],[2],[3])
) P
UNPIVOT + MERGE: 일괄 저장
-- 컬럼 기반 임시테이블을 행으로 풀어서 MERGE
MERGE INTO TSZM_GOAL_AMT AS T
USING (
SELECT TEAM_CODE,
CAST(REPLACE(MONTH_COL, 'M', '') AS INT) AS GOAL_MONTH,
ISNULL(GOAL_AMOUNT, 0) AS GOAL_AMOUNT
FROM #COLS
UNPIVOT (
GOAL_AMOUNT FOR MONTH_COL IN (M01,M02,M03,M04,M05,M06,M07,M08,M09,M10,M11,M12)
) AS U
) AS S
ON T.DEPT_CODE = S.TEAM_CODE AND T.GOAL_MONTH = S.GOAL_MONTH
WHEN MATCHED THEN UPDATE SET GOAL_AMOUNT = S.GOAL_AMOUNT
WHEN NOT MATCHED THEN INSERT (...) VALUES (...);
'DB' 카테고리의 다른 글
| MSSQL 인덱스의 INCLUDE, 이거 모르면 인덱스를 반만 쓰는 거다 (0) | 2026.05.19 |
|---|---|
| PostgreSQL, 왜 다들 Postgres 쓰라고 하는지 이제 알겠다 (0) | 2026.05.12 |
| [DB] 트랜잭션 완전 정리 (0) | 2025.09.23 |
| [DB] 데이터베이스 키(KEY) 종류 정리 (0) | 2025.09.23 |