๐งท PIVOT ์ฐ์ฐ
PIVOT ์ฐ์ฐ์ ๋ฐ์ดํฐ๋ฅผ ํ์์ ์ด๋ก ๋ณํํ๋ ๊ธฐ๋ฅ์ ๊ฐ์ง ํจ์์ด๋ค. ์ง์ ํ ์ด์ ๊ฐ์ ์ด๋ก PIVOTํ๊ณ , ์ง๊ณํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ทธ ์ด์ ๋ฐ์ดํฐ๋ฅผ ์ง๊ณํ๋ค.
PIVOT [XML]
(
์ง๊ณํจ์(expr) [AS ๋ณ์นญ]
FOR column
IN (
expr [AS ๋ณ์นญ] |
Subquery |
ANY
)
)
- ์ง๊ณํจ์(expr) : ์ง๊ณํจ์์ ์ง๊ณํ ์ด์ ์ง์ ํ๊ณ , ์ฌ๋ฌ ๊ฐ์ ์ง๊ณํจ์๋ฅผ ์ง์ ํ ์ ์๋ค.
- FOR ์ : FOR ์ ์ PIVOT ํ ์ด์ ์ง์ ํ๋ค.
- ๋ค์์ ์ด์ ๊ธฐ์ ํ ์ ์๋ค.
- FOR ์ ์ ์ง์ ๋์ง ์์ ์ด์ ๊ธฐ์ค์ผ๋ก ์ง๊ณ๋๊ธฐ ๋๋ฌธ์ Inline View๋ฅผ ํตํด ์ฌ์ฉํ ์ด์ ์ง์ ํด์ผ ํ๋ค.
- IN ์ ์ PIVOT ํ ์ด ๊ฐ (= FOR ์ ์์ ์ง์ ๋ ์ด ๊ฐ)์ ์ง์ ํ๋ค.
- IN์ ์ง์ ๋ ์ด ๊ฐ์ ๋ณ์นญ์ ํตํด ์ํ๋ ์ด๋ฆ์ผ๋ก ์ง์ ํ ์ ์๋ค.
- XML ์ต์ ์ ์ฌ์ฉํ๋ฉด Subquery ํน์ ANY ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
์์ # 1
SELECT *
FROM(
SELECT STANDARD_COST, CATEGORY_ID, SUBSTR(DESCRIPTION,0,1) AS DESCS
FROM PRODUCTS
)
PIVOT(
SUM(STANDARD_COST)
FOR CATEGORY_ID
IN (1, 2, 5, 4)
);
FOR ์ ์ ๊ฐ(IN ์ ์ ๊ฐ)๋ค์ ์ด๋ก ๋ณํ๋๋ค. PIVOT ์ ์ ์ง๊ณํจ์์ ์ฌ์ฉ๋ STANDARD_COST ์ปฌ๋ผ๊ณผ FOR ์ ์ ๋ช ์๋์ง ์์ DESCS ์ปฌ๋ผ์ ๊ธฐ์ค์ผ๋ก ์ง๊ณ๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก, Inline View๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉํ ์ด์ ์ง์ ํด์ผ ํ๋ค.
์์ #2 ๋ณ์นญ
SELECT *
FROM(
SELECT STANDARD_COST, CATEGORY_ID, SUBSTR(DESCRIPTION,0,1) AS DESCS
FROM PRODUCTS
)
PIVOT(
SUM(STANDARD_COST) AS COST
FOR CATEGORY_ID
IN (1 AS ID01, 2 AS ID02, 4 AS ID04, 5 AS ID05)
);
FOR์ ๊ณผ IN์ ์ ๋ชจ๋ ๋ณ์นญ์ ์ง์ ํ ์ ์๋ค. IN๋ณ์นญ_FOR๋ณ์นญ ํ์์ผ๋ก ์ด ๋ช ์ด ์ง์ ๋๋ค.
[ ๋ณ์นญ ์์ ]
1 | 1 AS ID01 | |
SUM(COST) | 1 | ID01 |
SUM(COST) AS COST | 1_COST | ID01_COST |
์์ #3 ๋ค์ค ์ด
PIVOT ์ ์ ๋ค์์ ์ง๊ณํจ์๋ฅผ ์ง์ํ๋ค.
SELECT *
FROM(
SELECT STANDARD_COST, LIST_PRICE, CATEGORY_ID, SUBSTR(DESCRIPTION,0,1) AS DESCS
FROM PRODUCTS
)
PIVOT(
SUM(STANDARD_COST) AS COST, MAX(LIST_PRICE) AS PRICE
FOR CATEGORY_ID
IN (1, 2, 4, 5)
);
์ง๊ณํจ์์์ ์ฌ๋ฌ ๊ฐ์ ์ง๊ณํจ์๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ, ์๋ก ๊ตฌ๋ถํ ์ ์๋ ๋ณ์นญ์ ์ง์ ํด์ผ ํ๋ค. ์ง์ ํ์ง ์์ผ๋ฉด ORA-00918: ์ด์ ์ ์๊ฐ ์ ๋งคํฉ๋๋ค
์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์๋ค.
์ง๊ณํจ์ ๋ฟ๋ง ์๋๋ผ FOR ์ ์๋ ๋ค์์ ์ด์ ๊ธฐ์ ํ ์ ์๋ค.
SELECT *
FROM(
SELECT STANDARD_COST, LIST_PRICE, CATEGORY_ID,
SUBSTR(DESCRIPTION,0,1) AS DESCS, MOD(PRODUCT_ID,2) AS PRD_ID
FROM PRODUCTS
)
PIVOT(
SUM(STANDARD_COST) AS COST, MAX(LIST_PRICE) AS PRICE
FOR (PRD_ID, CATEGORY_ID)
IN ((0,1) AS ID01,(0,2) AS ID02,(0,4) AS ID04,(0,5) AS ID05,(1,1) AS ID11,(1,2) AS ID12,(1,4) AS ID14,(1,5) AS ID15)
);
FO R์ ์ ๋ค์์ ์ด์ ์ฌ์ฉํ ๊ฒฝ์ฐ, FOR ์ ์ ๊ดํธ ์์ ์ด ์์์ IN ์ ์ ๊ดํธ ์์ ์ด ๊ฐ ์์๊ฐ ์ผ์นํด์ผ ํ๋ค.
์์ #4 Subquery & ANY
ORACLE์ IN ์ ์ ๋์ ๊ฐ ์งํฉ์ ์ง์ ์ฌ์ฉํ๊ธฐ ์ด๋ ค์ฐ๋ฉฐ, ๋์ XML PIVOT์ ์ฌ์ฉํ์ฌ ๋์ ๊ฐ ์งํฉ์ ๋ค๋ฃฐ ์ ์๋ค. ๊ทธ๋ฌ๋ XML ์์ด Subquery ๋ฐ ANY ์ฐ์ฐ์๋ก ๋์ ๊ฐ ์งํฉ์ ๋ค๋ฃจ๋ ๊ฒ์ ์ด๋ ต๋ค.
[ Subquery ]
SELECT *
FROM(
SELECT STANDARD_COST, CATEGORY_ID
FROM PRODUCTS
)
PIVOT XML
(
SUM(STANDARD_COST) AS COST
FOR (CATEGORY_ID)
IN (
SELECT DISTINCT CATEGORY_ID
FROM PRODUCTS
)
);
[ ANY ]
SELECT *
FROM(
SELECT STANDARD_COST, CATEGORY_ID, SUBSTR(DESCRIPTION,0,1) AS DESCS
FROM PRODUCTS
)
PIVOT XML
(
SUM(STANDARD_COST) AS COST
FOR (CATEGORY_ID)
IN (ANY)
);
์์ #5 ๋์ SQL
ORACLE์์๋ IN ์ ์ ๋์ ๊ฐ ์งํฉ์ ์ง์ ์ฌ์ฉํ ์๋ ์์ง๋ง, Dynamic SQL์ ํตํด ์ด๋ฅผ ๊ตฌํํ ์ ์๋ค.
VAR RESULT REFCURSOR;
DECLARE
dynamic_sql VARCHAR(4000);
BEGIN
FOR X IN (SELECT DISTINCT CATEGORY_ID FROM PRODUCTS)
LOOP
dynamic_sql := dynamic_sql || '''' || X.CATEGORY_ID || '''' || ', ';
END LOOP;
dynamic_sql := SUBSTR(dynamic_sql, 1, LENGTH(dynamic_sql) - 2);
dynamic_sql :=
'
SELECT *
FROM(
SELECT STANDARD_COST, CATEGORY_ID
FROM PRODUCTS
)
PIVOT
(
SUM(STANDARD_COST) AS COST
FOR (CATEGORY_ID)
IN (' || dynamic_sql || ')
)
';
DBMS_OUTPUT.PUT_LINE('Dynamic SQL: ' || dynamic_sql);
OPEN :RESULT FOR dynamic_sql;
END;
/
PRINT RESULT
๐๏ธ UNPIVOT
UNPIVOT ์ฐ์ฐ์ PIVOT ์ฐ์ฐ๊ณผ๋ ๋ฐ๋๋ก ๋ฐ์ดํฐ๋ฅผ ์ด์์ ํ์ผ๋ก ๋ณํํ๋ ํจ์์ด๋ค. ์ง์ ํ ์ด์ ๊ฐ์ ํ์ผ๋ก UNPIVOTํ๋ค.
UNPIVOT [{INCLUDE | EXCLUDE} NULLS]
(
column
FOR column
IN column [AS literal]
)
- UNPIVOT ์ : UNPIVOT ์ ์ UNPIVOT ๋ ๊ฐ์ ํฌํจํ ์ด์ ์ด๋ฆ์ ์ง์ ํ๋ค.
- INCLUDE NULLS : NULL ๊ฐ ํฌํจ
- EXCLUDE NULLS : NULL ๊ฐ ๋ฏธ ํฌํจ
- ์ต์ ์ ์ง์ ํ์ง ์์ผ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก NULL ๊ฐ์ ํฌํจํ์ง ์๋๋ค.
- FOR ์ : FOR ์ ์ UNPIVOT ์ ์ ๋ช ์ํ ์ด ์ด๋ฆ์ด ํฌํจํ ์ด์ ์ด๋ฆ์ ์ง์ ํ๋ค.
- IN ์ : IN ์ ์ UNPIVOT ์ ์ ๋ช ์ํ ์ด ๊ฐ๊ณผ ๋ฆฌํฐ๋ด ๊ฐ์ ์ง์ ํ๋ค.
์์ # 1
SELECT *
FROM (
SELECT FIRST_NAME, LAST_NAME
FROM CONTACTS
)
UNPIVOT(
NAMES FOR FIRST_LAST IN (FIRST_NAME, LAST_NAME)
)
IN ์ ์ ์ด ๊ฐ์ด UNPIVOT์ ์ ๋ช ์ํ ์ด ๊ฐ์ผ๋ก ์ด๋ํ๋ค. ๋ํ, IN ์ ์ ์ด ์ด๋ฆ์ FOR ์ ์ ๋ช ์ํ ์ด ๊ฐ์ผ๋ก ์ด๋ํ๋ค.
์์ # 2 ๋ณ์นญ
SELECT *
FROM (
SELECT FIRST_NAME, LAST_NAME
FROM CONTACTS
)
UNPIVOT(
NAMES FOR FIRST_LAST IN (FIRST_NAME AS 'FIRST', LAST_NAME AS 'LAST')
)
IN ์ ์ ๋ณ์นญ์ ์ง์ ํ๋ฉด, FOR ์ ์ ๋ช ์ํ ์ด์ ๊ฐ์ด ์๋ ๋ณ์นญ์ผ๋ก ์ด ๊ฐ์ ๋ณ๊ฒฝ ํ ์ ์๋ค.
์์ # 3 ์ต์
SELECT *
FROM (
SELECT FIRST_NAME, '' AS LAST_NAME
FROM CONTACTS
)
UNPIVOT INCLUDE NULLS
(
NAMES FOR FIRST_LAST IN (FIRST_NAME AS 'FIRST', LAST_NAME AS 'LAST')
);
UNPIVOT ์ฐ์ฐ์ NULL ๊ฐ์ ํฌํจํ์ง ์์ง๋ง INCLUDE NULLS
์ ํตํด NULL ๊ฐ์ ๊ฒฐ๊ณผ์ ํฌํจ ํ ์ ์๋ค.
Reference
'DB > Oracle' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Oracle] LATERAL & APPLY JOIN ์ฐ์ฐ (0) | 2023.11.02 |
---|---|
[Oracle] Oracle ์ํ ๋ฐ์ดํฐ ๋ฒ ์ด์ค (0) | 2023.10.27 |