๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“ฆ MSSQL SQL Server/๐Ÿ—‚๏ธ MSSQL

[MSSQL] PIVOT.. ์œผ๋กœ ๋ฐ์ดํ„ฐ ๋“œ๋Ÿฌ๋ˆ•ํžˆ๊ธฐ

by ์‚๋šค์˜ค๋ฆฌ 2026. 5. 12.

PIVOT์ด๋ž€?

PIVOT์€ ํ…Œ์ด๋ธ”์˜ ํ–‰(row) ๋ฐ์ดํ„ฐ๋ฅผ ์—ด(column)์œผ๋กœ ๋ณ€ํ™˜ํ•ด ๊ฐ€๋กœํ˜• ์š”์•ฝ ๋ทฐ๋ฅผ ๋งŒ๋“œ๋Š” SQL ๋ฌธ๋ฒ•์ด๋‹ค.
์—‘์…€์˜ ํ”ผ๋ฒ— ํ…Œ์ด๋ธ”๊ณผ ์™„์ „ํžˆ ๊ฐ™์€ ๊ฐœ๋…์ด๋‹ค. ์„ธ๋กœ๋กœ ์Œ“์ธ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๋กœ๋กœ ํŽผ์ณ์„œ ํ•œ๋ˆˆ์— ๋น„๊ตํ•˜๊ธฐ ์ข‹์€ ํ˜•ํƒœ๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค.
๋ฐ˜๋Œ€๋กœ ์—ด์„ ๋‹ค์‹œ ํ–‰์œผ๋กœ ๋Œ๋ฆฌ๋Š” ๊ฑด UNPIVOT์ด ๋‹ด๋‹นํ•œ๋‹ค.

 

 

PIVOT ๋ณ€ํ™˜ ๊ตฌ์กฐ

ํด๋กœ๋“œ๊ฐ€ ๋งŒ๋“ค์–ด์ค€ ํ…Œ์ด๋ธ”

month ์ปฌ๋Ÿผ์˜ ๊ฐ ๊ฐ’(2024-01, 02, 03)์ด ์—ด ์ด๋ฆ„์œผ๋กœ ๋ณ€ํ™˜๋˜๊ณ , revenue ๊ฐ’์ด ๊ฐ ์…€์„ ์ฑ„์šฐ๋Š” ๊ตฌ์กฐ์ด๋‹ค.
์ด๊ฒƒ์ด PIVOT์˜ ํ•ต์‹ฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค.

 

 

PIVOT์ด ํ•„์š”ํ•œ ์ด์œ 

๊ฒŒ์ž„/๋งค์ถœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•˜๋‹ค ๋ณด๋ฉด ์ด๋Ÿฐ ์ƒํ™ฉ์ด ์ž์ฃผ ๋ฐœ์ƒํ•œ๋‹ค.

  • ์›”๋ณ„ ๋งค์ถœ์ด ์„ธ๋กœ๋กœ ์Œ“์—ฌ ์žˆ๋Š”๋ฐ, ๊ฐ€๋กœ๋กœ ํŽผ์ณ์„œ ์›”๋ณ„ ๋น„๊ต๋ฅผ ํ•ด์•ผ ํ•  ๋•Œ
  • ์„ธ๊ทธ๋จผํŠธ๋ณ„ ํ•ญ๋ชฉ ์ˆ˜์น˜๋ฅผ ํ•œ ํ–‰์— ๋‚˜๋ž€ํžˆ ๋†“๊ณ  ๋ณด๊ณ ์„œ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•  ๋•Œ
  • BI ๋Œ€์‹œ๋ณด๋“œ๋‚˜ ๋ณด๊ณ ์šฉ ์ฟผ๋ฆฌ์—์„œ ํฌ๋กœ์Šคํƒญ ํ˜•ํƒœ๊ฐ€ ํ•„์š”ํ•  ๋•Œ

 

 

๊ธฐ๋ณธ ๋ฌธ๋ฒ• ๊ตฌ์กฐ

SELECT *
FROM [ํ…Œ์ด๋ธ”๋ช…] ๋˜๋Š” [์„œ๋ธŒ์ฟผ๋ฆฌ]
PIVOT (
    ์ง‘๊ณ„ํ•จ์ˆ˜(์ง‘๊ณ„ํ• _์ปฌ๋Ÿผ) FOR ์—ด๋กœ_๋ฐ”๊ฟ€_์ปฌ๋Ÿผ IN ([๊ฐ’1], [๊ฐ’2], [๊ฐ’3])
) AS pvt;

3๊ฐ€์ง€ ํ•ต์‹ฌ ์š”์†Œ๋งŒ ๊ธฐ์–ตํ•˜๋ฉด ๋œ๋‹ค.

  • ์ง‘๊ณ„ํ•จ์ˆ˜(์ง‘๊ณ„ํ•  ์ปฌ๋Ÿผ) : ๊ฐ ์…€์— ๋“ค์–ด๊ฐˆ ๊ฐ’. SUM, AVG, AOUNT, MAX ๋“ฑ์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • FOR ์—ด๋กœ ๋ฐ”๊ฟ€ ์ปฌ๋Ÿผ : ํ–‰ ๊ฐ’์„ ์—ด ์ด๋ฆ„์œผ๋กœ ๋ฐ”๊ฟ€ ์ปฌ๋Ÿผ์„ ์ง€์ •ํ•œ๋‹ค.
  • IN ([๊ฐ’1], [๊ฐ’2], ...) : ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์งˆ ์—ด ์ด๋ฆ„ ๋ชฉ๋ก์„ ์ง์ ‘ ๋ช…์‹œํ•œ๋‹ค.

๊ธฐ๋ณธ ์‚ฌ์šฉ ์˜ˆ์‹œ

SELECT *
FROM (
    SELECT salesClass, month, revenue
    FROM sales_data
) AS src
PIVOT (
    SUM(revenue) FOR month IN ([2024-01], [2024-02], [2024-03])
) AS pvt;

๊ฒฐ๊ณผ:

salesClass 2024-01 2024-02 2024-03
A 100 150 200
B 80 120 90
  • FOR month IN (...) ์•ˆ์— ๋“ค์–ด๊ฐ€๋Š” ๊ฐ’์€ ์‹ค์ œ ๋ฐ์ดํ„ฐ์— ์กด์žฌํ•˜๋Š” month ์ปฌ๋Ÿผ ๊ฐ’์ด๋‹ค.
  • ๋Œ€๊ด„ํ˜ธ([ ])๋Š” ํ•˜์ดํ”ˆ(-) ๊ฐ™์€ ํŠน์ˆ˜๋ฌธ์ž๊ฐ€ ํฌํ•จ๋œ ์ปฌ๋Ÿผ๋ช…์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค.

 

 

PIVOT ์ž‘์„ฑ ์‹œ ํ•ต์‹ฌ ๊ทœ์น™

1) ์„œ๋ธŒ์ฟผ๋ฆฌ์— ํ•„์š”ํ•œ ์ปฌ๋Ÿผ๋งŒ ๋‚จ๊ฒจ์•ผ ํ•œ๋‹ค.

PIVOT์€ ์„œ๋ธŒ์ฟผ๋ฆฌ์— ์กด์žฌํ•˜๋Š” ์ปฌ๋Ÿผ ์ค‘ FOR ์ ˆ๊ณผ ์ง‘๊ณ„ ๋Œ€์ƒ ์ปฌ๋Ÿผ์„ ์ œ์™ธํ•œ ๋‚˜๋จธ์ง€๋ฅผ ์ž๋™์œผ๋กœ GROUP BY ๊ธฐ์ค€์œผ๋กœ ์‚ผ๋Š”๋‹ค.

-- โŒ ์ž˜๋ชป๋œ ์˜ˆ : gameDataId๊ฐ€ ์žˆ์œผ๋ฉด salesClass + gameDataId ์กฐํ•ฉ์œผ๋กœ ๊ทธ๋ฃน์ด ๋‚˜๋‰จ
SELECT *
FROM (
    SELECT salesClass, gameDataId, month, revenue  -- gameDataId๊ฐ€ ์˜๋„์น˜ ์•Š์€ ๊ทธ๋ฃน ๊ธฐ์ค€์ด ๋จ
    FROM sales_data
) AS src
PIVOT (
    SUM(revenue) FOR month IN ([2024-01], [2024-02], [2024-03])
) AS pvt;

-- โœ… ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ : ํ•„์š”ํ•œ ์ปฌ๋Ÿผ๋งŒ ๋ช…์‹œ
SELECT *
FROM (
    SELECT salesClass, month, revenue
    FROM sales_data
) AS src
PIVOT (
    SUM(revenue) FOR month IN ([2024-01], [2024-02], [2024-03])
) AS pvt;
PIVOT ์ฟผ๋ฆฌ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‹ค์ˆ˜ํ•˜๋Š” ๋ถ€๋ถ„์ด๋‹ค.
์„œ๋ธŒ์ฟผ๋ฆฌ์— ์ปฌ๋Ÿผ์ด ๋งŽ์œผ๋ฉด ๊ฒฐ๊ณผ ํ–‰์ด ์˜ˆ์ƒ๋ณด๋‹ค ๋งŽ์•„์ง€๋Š” ์ด์œ ๊ฐ€ ์—ฌ๊ธฐ์— ์žˆ๋‹ค.

2) In ์ ˆ์˜ ๊ฐ’์€ ๋ฐ˜๋“œ์‹œ ์‚ฌ์ „์— ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.

PIVOT์˜ ๊ฐ€์žฅ ํฐ ์ œ์•ฝ์€ IN ์ ˆ์— ๋“ค์–ด๊ฐˆ ์—ด ๊ฐ’์„ ์ฟผ๋ฆฌ ์ž‘์„ฑ ์‹œ์ ์— ์ง์ ‘ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค.

-- ์ปฌ๋Ÿผ์ด ๊ณ ์ •๋œ ๊ฒฝ์šฐ : ์ •์  PIVOT์œผ๋กœ ์ถฉ๋ถ„
FOR month IN ([2024-01], [2024-02], [2024-03])

-- ์ปฌ๋Ÿผ์ด ๋™์ ์œผ๋กœ ๋ฐ”๋€Œ๋Š” ๊ฒฝ์šฐ : ๋™์  PIVOT์ด ํ•„์š”ํ•˜๋‹ค (์•„๋ž˜์—์„œ ์„ค๋ช…)

๋™์  PIVOT (Dynamic PIVOT)

๋ฐ์ดํ„ฐ์— ๋”ฐ๋ผ ์—ด ๊ฐ’์ด ๋‹ฌ๋ผ์ง€๋Š” ๊ฒฝ์šฐ, ์ฆ‰ ์–ด๋–ค ๊ฐ’์ด ์˜ฌ์ง€ ๋ฏธ๋ฆฌ ์•Œ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” ๋™์ ์œผ๋กœ SQL์„ ์กฐ๋ฆฝํ•ด ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค.

DECLARE @cols NVARCHAR(MAX);
DECLARE @sql  NVARCHAR(MAX);

-- 1๋‹จ๊ณ„ : ์—ด๋กœ ๋งŒ๋“ค ๊ฐ’ ๋ชฉ๋ก์„ ๋™์ ์œผ๋กœ ์กฐํšŒ
SELECT @cols = STRING_AGG(QUOTENAME(month), ', ')
               WITHIN GROUP (ORDER BY month)
FROM (SELECT DISTINCT month FROM sales_data) AS t;

-- 2๋‹จ๊ณ„ : ๋™์  SQL ์กฐ๋ฆฝ
SET @sql = N'
            SELECT *
            FROM (
                SELECT salesClass, month, revenue
                FROM sales_data
            ) AS src
            PIVOT (
                SUM(revenue) FOR month IN (' + @cols + N')
            ) AS pvt;';

-- 3๋‹จ๊ณ„ : ์‹คํ–‰
EXEC sp_executesql @sql;

 

 

UNPIVOT : PIVOT์˜ ๋ฐ˜๋Œ€

์—ด(Column)์„ ๋‹ค์‹œ ํ–‰(Row)๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

SELECT salesClass, month, revenue
FROM (
    SELECT salesClass, [2024-01], [2024-02], [2024-03]
    FROM pivot_result
) AS src
UNPIVOT (
    revenue FOR month IN ([2024-01], [2024-02], [2024-03])
) AS unpvt;
  • PIVOT์œผ๋กœ ํŽผ์นœ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์‹œ ์„ธ๋กœ ํ˜•ํƒœ๋กœ ๋˜๋Œ๋ฆด ๋•Œ ํ™œ์šฉํ•œ๋‹ค.
  • ETL ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ๊ฐ€๋กœํ˜• ์›๋ณธ ๋ฐ์ดํ„ฐ๋ฅผ ์„ธ๋กœํ˜•์œผ๋กœ ์ •๊ทœํ™”ํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค.

 

 

PIVOT vs CASE WHEN ๋น„๊ต

PIVOT ์ด์ „์—๋Š” CASE WHEN์œผ๋กœ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

-- CASE WHEN ๋ฐฉ์‹
SELECT
    salesClass,
    SUM(CASE WHEN month = '2024-01' THEN revenue ELSE 0 END) AS [2024-01],
    SUM(CASE WHEN month = '2024-02' THEN revenue ELSE 0 END) AS [2024-02],
    SUM(CASE WHEN month = '2024-03' THEN revenue ELSE 0 END) AS [2024-03]
FROM sales_data
GROUP BY salesClass;
๊ตฌ๋ถ„ PIVOT CASE WHEN
๊ฐ€๋…์„ฑ ์—ด์ด ๋งŽ์„์ˆ˜๋ก ๊น”๋” ์—ด์ด ๋งŽ์„์ˆ˜๋ก ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์ง
์œ ์—ฐ์„ฑ IN ์ ˆ ๊ฐ’ ๊ณ ์ • ํ•„์š” ์กฐ๊ฑด์„ ์ž์œ ๋กญ๊ฒŒ ๋ณ€ํ˜• ๊ฐ€๋Šฅ
๋™์  ์—ด ๋™์  SQL ํ•„์š” ๋™์  SQL ํ•„์š”
์„ฑ๋Šฅ ์œ ์‚ฌ ์œ ์‚ฌ
NULL ์ฒ˜๋ฆฌ NULL ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ ELSE 0์œผ๋กœ ์ œ์–ด ๊ฐ€๋Šฅ
  • ์—ด ์ˆ˜๊ฐ€ ๋งŽ๊ณ  ๊ณ ์ •๋˜์–ด ์žˆ๋‹ค๋ฉด PIVOT์ด ๋” ๊น”๋”ํ•˜๋‹ค.
  • NULL์„ 0์œผ๋กœ ๋ฐ”๊พธ๋Š” ๋“ฑ ์„ธ๋ถ€ ์ œ์–ด๊ฐ€ ํ•„์š”ํ•˜๋ฉด CASE WHEN์ด ์œ ๋ฆฌํ•˜๋‹ค.

NULL ์ฒ˜๋ฆฌ: PIVOT ๊ฒฐ๊ณผ์˜ NULL ์ฑ„์šฐ๊ธฐ

PIVOT์—์„œ ํ•ด๋‹น ๊ฐ’์ด ์—†์œผ๋ฉด ์ž๋™์œผ๋กœ NULL์ด ๋“ค์–ด๊ฐ„๋‹ค.
์ด๋ฅผ 0์ด๋‚˜ ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ์ฑ„์šฐ๋ ค๋ฉด ISNULL ๋˜๋Š” COALSCE๋กœ ๊ฐ์‹ธ์•ผ ํ•œ๋‹ค.

SELECT
    salesClass,
    ISNULL([2024-01], 0) AS [2024-01],
    ISNULL([2024-02], 0) AS [2024-02],
    ISNULL([2024-03], 0) AS [2024-03]
FROM (
    SELECT salesClass, month, revenue
    FROM sales_data
) AS src
PIVOT (
    SUM(revenue) FOR month IN ([2024-01], [2024-02], [2024-03])
) AS pvt;

 

 

PIVOT ์‚ฌ์šฉ ์‹œ ์ฃผ์˜์‚ฌํ•ญ

โœ” ์„œ๋ธŒ์ฟผ๋ฆฌ ์ปฌ๋Ÿผ์„ ์ตœ์†Œํ™”ํ•˜์ž

  • ์ง‘๊ณ„ ๊ธฐ์ค€, FOR ๋Œ€์ƒ, ์ง‘๊ณ„ ์ปฌ๋Ÿผ ๋”ฑ 3๊ฐ€์ง€๋งŒ ๋‚จ๊ฒจ์•ผ ์˜๋„ํ•œ ๊ทธ๋ฃนํ•‘์ด ๋œ๋‹ค.

โœ” ๋™์  PIVOT์€ SQL ์ธ์ ์…˜์„ ์ฃผ์˜ํ•˜์ž

  • QUOTENAME()์„ ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉํ•ด ์ปฌ๋Ÿผ๋ช…์„ ๊ฐ์‹ธ์ค˜์•ผ ํŠน์ˆ˜ ๋ฌธ์ž๋‚˜ ์•…์˜์ ์ธ ์ž…๋ ฅ์„ ๋ฐฉ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.

โœ” NULL์„ ๋ฐ˜๋“œ์‹œ ์ฒ˜๋ฆฌํ•˜์ž

  • ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ์กฐํ•ฉ์€ NULL๋กœ ์ฑ„์›Œ์ง„๋‹ค. ์ง‘๊ณ„ ๋ชฉ์ ์ด๋ผ๋ฉด ISNULL(์ปฌ๋Ÿผ, 0)์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค.

โœ” IN ์ ˆ ๊ฐ’์˜ ์ˆœ์„œ๋„ ๊ฒฐ๊ณผ ์—ด ์ˆœ์„œ์— ์˜ํ–ฅ์„ ์ค€๋‹ค

  • ๋™์  PIVOT์—์„œ ORDER BY๋ฅผ ํ†ตํ•ด ์—ด ์ˆœ์„œ๋ฅผ ์ œ์–ดํ•˜์ž.

 

 

๊ฒฐ๋ก  : ํ•œ ์ค„ ์š”์•ฝ

PIVOT์€ ์„ธ๋กœ๋กœ ์Œ“์ธ ํ–‰ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๋กœ๋กœ ํŽผ์ณ ํฌ๋กœ์Šคํƒญ ํ˜•ํƒœ์˜ ์š”์•ฝ ๋ทฐ๋ฅผ ๋งŒ๋“œ๋Š” MSSQL ๋ฌธ๋ฒ•์œผ๋กœ, ์„œ๋ธŒ์ฟผ๋ฆฌ ์ปฌ๋Ÿผ ์„ค๊ณ„์™€ ๋™์  PIVOT ํŒจํ„ด๋งŒ ์ตํžˆ๋ฉด ๋ณด๊ณ ์„œ/๋Œ€์‹œ๋ณด๋“œ์šฉ ์ฟผ๋ฆฌ๋ฅผ ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

References

https://learn.microsoft.com/ko-kr/sql/t-sql/queries/from-using-pivot-and-unpivot
https://learn.microsoft.com/ko-kr/sql/t-sql/functions/string-agg-transact-sql