공부/MSSQL

MSSQL PIVOT

da_won_2023 2023. 8. 17. 23:51
SMALL

PIVOT이라 함은 행을 열로 바꾸는 것을 의미한다.

만약 아래와 같은 테이블이 있다고 가정해보자.

과일이름
과일 개수
사과
10
바나나
20
샤인머스캣
30
복숭아
10
레몬
20
30
오렌지
10

예제 데이터는 아래와같이 생성했다.

 

 

DECLARE @TEMP TABLE (
	FRUIT_NAME NVARCHAR(20),
	BUY_AMT INT
)

INSERT INTO @TEMP VALUES('사과',10)
INSERT INTO @TEMP VALUES('바나나',20)
INSERT INTO @TEMP VALUES('샤인머스캣',30) 
INSERT INTO @TEMP VALUES('복숭아',10)
INSERT INTO @TEMP VALUES('레몬',20)
INSERT INTO @TEMP VALUES('귤',30)
INSERT INTO @TEMP VALUES('오렌지',10)

 

 

이 테이블을 PIVOT을 사용하여 아래와 같은 형태로 만드려고 한다.

과일이름
10
20
30
NULL
NULL
30
레몬
NULL
20
NULL
바나나
NULL
20
NULL
복숭아
10
NULL
NULL
사과
10
NULL
NULL
샤인머스캣
NULL
NULL
30
오렌지
10
NULL
NULL

구문은 다음과 같다.

SELECT [컬럼] FROM [적용할 테이블] [TABLE_ALIAS]

PIVOT( 집계함수([컬럼]) FOR [컬럼] IN (PIVOT할 컬럼) ) [PIVOT_ALIAS]

실행 쿼리는

 

 

SELECT * FROM @TEMP T
PIVOT( SUM(BUY_AMT) FOR BUY_AMT IN ([10],[20],[30]) ) P

 

여기서 만약 테스트 데이터가

과일이름
과일 개수
사과
10
바나나
20
샤인머스캣
30
복숭아
10
레몬
20
30
오렌지
10
오렌지
10

라고 가정했을 때 위의 방법으로 PIVOT을 돌리면 아래와 같이 나온다.

과일이름
10
20
30
NULL
NULL
30
레몬
NULL
20
NULL
바나나
NULL
20
NULL
복숭아
10
NULL
NULL
사과
10
NULL
NULL
샤인머스캣
NULL
NULL
30
오렌지
20
NULL
NULL

오렌지가 10 컬럼에서 20개인 것을 볼 수 있다.

따라서 PIVOT을 사용할 때 집계할 컬럼이 있다면

아래와 같이 사용해주는 것이 좋다.

실행 쿼리는

 

 

SELECT * FROM (SELECT FRUIT_NAME,SUM(BUY_AMT) BUY_AMT FROM @TEMP GROUP BY FRUIT_NAME) T
PIVOT( SUM(BUY_AMT) FOR BUY_AMT IN ([10],[20],[30]) ) P

 

 

말로 풀어 설명하자면

집계할 컬럼에 대해서는 PIVOT을 적용할 테이블에서 미리 집계를 한 후 PIVOT을 하는 것이다.

여기서 추가로 응용을 해보자면

10
20
30
복숭아
레몬
사과
바나나
샤인머스캣
NULL
오렌지
NULL

데이터가 위처럼 각 각의 양에 맞는 컬럼에 과일 이름이 들어가야 하며 NULL을 최소화시켜야한다고 가정을 했을 때

MSSQL ROW_NUMBER 포스팅에서 했던 것처럼 ROW_NUMBER함수를 사용하여 SQL문을 작성할 수 있다.

실행 쿼리는 아래와 같다.

 

 

 

 

SELECT 
		MAX(CASE WHEN BUY_AMT = 10 THEN FRUIT_NAME END ) [10]
	,	MAX(CASE WHEN BUY_AMT = 20 THEN FRUIT_NAME END ) [20]
	,	MAX(CASE WHEN BUY_AMT = 30 THEN FRUIT_NAME END ) [30]
FROM (
	SELECT 
			FRUIT_NAME
		,	BUY_AMT
		,	ROW_NUMBER() OVER(PARTITION BY BUY_AMT ORDER BY BUY_AMT) ROWNUM
	FROM (
		SELECT 
				FRUIT_NAME
			,	SUM(BUY_AMT) BUY_AMT
		FROM @TEMP
		GROUP BY FRUIT_NAME
	) A
) A
GROUP BY ROWNUM
LIST