artarad-oracle-database

عملگر PIVOT و UNPIVOT در اوراکل نسخه ۱۱g

عملگر PIVOT و UNPIVOT در پایگاه‌داده اراکل نسخه ۱۱g

سعی بر آن است تا در این نوشتار چگونگی استفاده از عملگرهای جدید PIVOT و UNPIVOT در نسخه ۱۱g به همراه ارائه یک راهکار مناسب برای عملکرد مشابه در نسخه‌های قبل از ۱۱g شرح داده شود.

PIVOT
عملگر PIVOT داده‌ها را از سطرهای مختلف می‌گیرد، پس از جمع‌آوری آن‌ها را به ستون مبدل می‌سازد. برای مشاهده نحوه عملکرد این عملگر ما به ایجاد یک جدول تست نیاز داریم.

CREATE TABLE pivot_test (

id NUMBER,

customer_id NUMBER,

product_code VARCHAR2(5),

quantity NUMBER

);

INSERT INTO pivot_test VALUES (1, 1, ‘A’, 10);

INSERT INTO pivot_test VALUES (2, 1, ‘B’, 20);

INSERT INTO pivot_test VALUES (3, 1, ‘C’, 30);

INSERT INTO pivot_test VALUES (4, 2, ‘A’, 40);

INSERT INTO pivot_test VALUES (5, 2, ‘C’, 50);

INSERT INTO pivot_test VALUES (6, 3, ‘A’, 60);

INSERT INTO pivot_test VALUES (7, 3, ‘B’, 70);

INSERT INTO pivot_test VALUES (8, 3, ‘C’, 80);

INSERT INTO pivot_test VALUES (9, 3, ‘D’, 90);

INSERT INTO pivot_test VALUES (10, 4, ‘A’, 100);

COMMIT;

بنابراین داده‌های تستی ما به شکل زیر ایجاد می‌شود.

SELECT * FROM pivot_test;

ID CUSTOMER_ID PRODU QUANTITY

———- ———– —– ———-

۱ ۱ A 10

۲ ۱ B 20

۳ ۱ C 30

۴ ۲ A 40

۵ ۲ C 50

۶ ۳ A 60

۷ ۳ B 70

۸ ۳ C 80

۹ ۳ D 90

۱۰ ۴ A 100

۱۰ rows selected.

SQL>

در وضعیت اولیه عملگر PIVOT کاملاً محدود است. ما ملزم به استفاده از عبارت IN برای فهرست نمودن مقادیر مورد نیاز PIVOT می‌باشیم.

SELECT *

FROM (SELECT product_code, quantity

FROM pivot_test)

PIVOT (SUM(quantity) AS sum_quantity FOR (product_code) IN (‘A’ AS a, ‘B’ AS b, ‘C’ AS c));

A_SUM_QUANTITY B_SUM_QUANTITY C_SUM_QUANTITY

————– ————– ————–

۲۱۰ ۹۰ ۱۶۰

۱ row selected.

SQL>

در صورتی که بخواهیم تغییری به‌وسیله customer انجام دهیم، ستون CUSTOMER_ID را به سادگی وارد فهرست انتخابی می نماییم.

SELECT *

FROM (SELECT customer_id, product_code, quantity

FROM pivot_test)

PIVOT (SUM(quantity) AS sum_quantity FOR (product_code) IN (‘A’ AS a, ‘B’ AS b, ‘C’ AS c))

ORDER BY customer_id;

CUSTOMER_ID A_SUM_QUANTITY B_SUM_QUANTITY C_SUM_QUANTITY

———– ————– ————– ————–

۱ ۱۰ ۲۰ ۳۰

۲ ۴۰ ۵۰

۳ ۶۰ ۷۰ ۸۰

۴ ۱۰۰

۴ rows selected.

SQL>

در نسخه‌های قبل از ۱۱g برای داشتن نتیجه مشابه از عملگر DECODE به همراه عملگرهای جمع استفاده می‌شد.

SELECT SUM(DECODE(product_code, ‘A’, quantity, 0)) AS a_sum_quantity,

SUM(DECODE(product_code, ‘B’, quantity, 0)) AS b_sum_quantity,

SUM(DECODE(product_code, ‘C’, quantity, 0)) AS c_sum_quantity

FROM pivot_test

ORDER BY customer_id;

A_SUM_QUANTITY B_SUM_QUANTITY C_SUM_QUANTITY

————– ————– ————–

۲۱۰ ۹۰ ۱۶۰

۱ row selected.

SQL>

SELECT customer_id,

SUM(DECODE(product_code, ‘A’, quantity, 0)) AS a_sum_quantity,

SUM(DECODE(product_code, ‘B’, quantity, 0)) AS b_sum_quantity,

SUM(DECODE(product_code, ‘C’, quantity, 0)) AS c_sum_quantity

FROM pivot_test

GROUP BY customer_id

ORDER BY customer_id;

CUSTOMER_ID A_SUM_QUANTITY B_SUM_QUANTITY C_SUM_QUANTITY

———– ————– ————– ————–

۱ ۱۰ ۲۰ ۳۰

۲ ۴۰ ۰ ۵۰

۳ ۶۰ ۷۰ ۸۰

۴ ۱۰۰ ۰ ۰

۴ rows selected.

SQL>

اضافه نمودن عبارت XML به عملگر PIVOT، این قابلیت را برای ما مهیا می‌سازد که نتایج تولید شده توسط PIVOT را به فرم XML تبدیل نماییم. همچنین این عمل باعث انعطاف‌پذیری بیشتر PIVOT می‌گردد و به ما این امکان را می‌دهد که عبارت IN را با یک subquery یا عبارت ANY جایگزین نماییم.

SET LONG 10000

SELECT *

FROM (SELECT product_code, quantity

FROM pivot_test)

PIVOT XML (SUM(quantity) AS sum_quantity FOR (product_code) IN (SELECT DISTINCT product_code 

FROM pivot_test

WHERE id < 10));

product_code_XML

—————————————————————————————————-

<PivotSet><item><column name = “PRODUCT_CODE”>A</column><column name = “SUM_QUANTITY”>210</column></

item><item><column name = “PRODUCT_CODE”>B</column><column name = “SUM_QUANTITY”>90</column></item><

item><column name = “PRODUCT_CODE”>C</column><column name = “SUM_QUANTITY”>160</column></item><item>

<column name = “PRODUCT_CODE”>D</column><column name = “SUM_QUANTITY”>90</column></item></PivotSet>

۱ row selected.

SQL>

SELECT *

FROM (SELECT product_code, quantity

FROM pivot_test)

PIVOT XML (SUM(quantity) AS sum_quantity FOR (product_code) IN (ANY));

product_code_XML

—————————————————————————————————-

<PivotSet><item><column name = “PRODUCT_CODE”>A</column><column name = “SUM_QUANTITY”>210</column></

item><item><column name = “PRODUCT_CODE”>B</column><column name = “SUM_QUANTITY”>90</column></item><

item><column name = “PRODUCT_CODE”>C</column><column name = “SUM_QUANTITY”>160</column></item><item>

<column name = “PRODUCT_CODE”>D</column><column name = “SUM_QUANTITY”>90</column></item></PivotSet>

۱ row selected.

SQL>

بار دیگر، نتایج میتواند توسط customer به بخش‌های جداگانه تقسیم شود طوری که هر customer XML، به عنوان ردیفی جداگانه نمایش داده شود.

SET LONG 10000

SELECT *

FROM (SELECT customer_id, product_code, quantity

FROM pivot_test)

PIVOT XML (SUM(quantity) AS sum_quantity FOR (product_code) IN (SELECT DISTINCT product_code 

FROM pivot_test));

CUSTOMER_ID

———–

PRODUCT_CODE_XML

—————————————————————————————————-

۱

<PivotSet><item><column name = “PRODUCT_CODE”>A</column><column name = “SUM_QUANTITY”>10</column></i

tem><item><column name = “PRODUCT_CODE”>B</column><column name = “SUM_QUANTITY”>20</column></item><i

tem><column name = “PRODUCT_CODE”>C</column><column name = “SUM_QUANTITY”>30</column></item><item><c

olumn name = “PRODUCT_CODE”>D</column><column name = “SUM_QUANTITY”></column></item></PivotSet>

۲

<PivotSet><item><column name = “PRODUCT_CODE”>A</column><column name = “SUM_QUANTITY”>40</column></i

tem><item><column name = “PRODUCT_CODE”>B</column><column name = “SUM_QUANTITY”></column></item><ite

CUSTOMER_ID

———–

PRODUCT_CODE_XML

—————————————————————————————————-

m><column name = “PRODUCT_CODE”>C</column><column name = “SUM_QUANTITY”>50</column></item><item><col

umn name = “PRODUCT_CODE”>D</column><column name = “SUM_QUANTITY”></column></item></PivotSet>

۳

<PivotSet><item><column name = “PRODUCT_CODE”>A</column><column name = “SUM_QUANTITY”>60</column></i

tem><item><column name = “PRODUCT_CODE”>B</column><column name = “SUM_QUANTITY”>70</column></item><i

tem><column name = “PRODUCT_CODE”>C</column><column name = “SUM_QUANTITY”>80</column></item><item><c

olumn name = “PRODUCT_CODE”>D</column><column name = “SUM_QUANTITY”>90</column></item></PivotSet>

CUSTOMER_ID

———–

PRODUCT_CODE_XML

—————————————————————————————————-

۴

<PivotSet><item><column name = “PRODUCT_CODE”>A</column><column name = “SUM_QUANTITY”>100</column></

item><item><column name = “PRODUCT_CODE”>B</column><column name = “SUM_QUANTITY”></column></item><it

em><column name = “PRODUCT_CODE”>C</column><column name = “SUM_QUANTITY”></column></item><item><colu

mn name = “PRODUCT_CODE”>D</column><column name = “SUM_QUANTITY”></column></item></PivotSet>

۴ rows selected.

SQL>

UNPIVOT
عملگر UNPIVOT داده‌های ستونی را به سطرهای جداگانه تبدیل می‌نماید. برای مشاهده عملگر این دستور نیاز به ایجاد یک جدول تست داریم.

CREATE TABLE unpivot_test (

id NUMBER,

customer_id NUMBER,

product_code_a NUMBER,

product_code_b NUMBER,

product_code_c NUMBER,

product_code_d NUMBER

);

INSERT INTO unpivot_test VALUES (1, 101, 10, 20, 30, NULL);

INSERT INTO unpivot_test VALUES (2, 102, 40, NULL, 50, NULL);

INSERT INTO unpivot_test VALUES (3, 103, 60, 70, 80, 90);

INSERT INTO unpivot_test VALUES (4, 104, 100, NULL, NULL, NULL);

COMMIT;

بنابراین داده‌های تستی ما به صورت زیر مشاهده می‌شوند:

SELECT * FROM unpivot_test;

ID CUSTOMER_ID PRODUCT_CODE_A PRODUCT_CODE_B PRODUCT_CODE_C PRODUCT_CODE_D

———- ———– ————– ————– ————– ————–

۱ ۱۰۱ ۱۰ ۲۰ ۳۰

۲ ۱۰۲ ۴۰ ۵۰

۳ ۱۰۳ ۶۰ ۷۰ ۸۰ ۹۰

۴ ۱۰۴ ۱۰۰

۴ rows selected.

SQL>

عملگر UNPIVOT داده‌های ستونی را به سطرهای جداگانه تبدیل می‌نماید.

SELECT *

FROM unpivot_test

UNPIVOT (quantity FOR product_code IN (product_code_a AS ‘A’, product_code_b AS ‘B’, product_code_c AS ‘C’, product_code_d AS ‘D’));

ID CUSTOMER_ID P QUANTITY

———- ———– – ———-

۱ ۱۰۱ A 10

۱ ۱۰۱ B 20

۱ ۱۰۱ C 30

۲ ۱۰۲ A 40

۲ ۱۰۲ C 50

۳ ۱۰۳ A 60

۳ ۱۰۳ B 70

۳ ۱۰۳ C 80

۳ ۱۰۳ D 90

۴ ۱۰۴ A 100

۱۰ rows selected.

SQL>

چند نکته در خصوص query وجود دارد:
• نام ستون‌های مورد نیاز در این مثال QUANTITY و PRODUCT_CODE درون عبارت UNPIVOT تعریف شده‌اند و در خصوص هر نامی که در جدول وجود ندارد می‌تواند اعمال شود.
• ستون‌ها برای UNPIVOT شدن باید در عبارت IN لحاظ گردد.
• مقدار عبارت PRODUCT_CODE برابر با نام ستون مأخوذه قرار خواهد گرفت مگر آنکه آن را برابر مقدار دیگری قرار دهید.
• عبارت EXCLUDE NULLS به صورت پیشفرض مورد استفاده قرار می‌گیرد، برای جایگزینی مقدار پیشفرض از عبارت INCLUDE NULLS استفاده نمایید.
در query زیر نحوه وارد نمودن عبارت INCLUDE NULLS نمایش داده شده است.

SELECT *

FROM unpivot_test

UNPIVOT INCLUDE NULLS (quantity FOR product_code IN (product_code_a AS ‘A’, product_code_b AS ‘B’, product_code_c AS ‘C’, product_code_d AS ‘D’));

ID CUSTOMER_ID P QUANTITY

———- ———– – ———-

۱ ۱۰۱ A 10

۱ ۱۰۱ B 20

۱ ۱۰۱ C 30

۱ ۱۰۱ D

۲ ۱۰۲ A 40

۲ ۱۰۲ B

۲ ۱۰۲ C 50

۲ ۱۰۲ D

۳ ۱۰۳ A 60

۳ ۱۰۳ B 70

۳ ۱۰۳ C 80

ID CUSTOMER_ID P QUANTITY

———- ———– – ———-

۳ ۱۰۳ D 90

۴ ۱۰۴ A 100

۴ ۱۰۴ B

۴ ۱۰۴ C

۴ ۱۰۴ D

۱۶ rows selected.

SQL>

در نسخه‌های ماقبل ۱۱g برای بدست آوردن نتایج فوق از عملگر DECODE و یک جدول محوری به همراه تعداد سطرهای مناسب بهره می‌بریم. در مثال زیر از عبارت CONNECT BY در query برای ایجاد تعداد سطرهای مورد نیاز برای UNPIVOT استفاده گردیده است.

SELECT id,

customer_id,

DECODE(unpivot_row, 1, ‘A’,

۲, ‘B’,

۳, ‘C’,

۴, ‘D’,

‘N/A’) AS product_code,

DECODE(unpivot_row, 1, product_code_a,

۲, product_code_b,

۳, product_code_c,

۴, product_code_d,

‘N/A’) AS quantity

FROM unpivot_test,

(SELECT level AS unpivot_row FROM dual CONNECT BY level <= 4)

ORDER BY 1,2,3;

ID CUSTOMER_ID PRO QUANTITY

———- ———– — ———-

۱ ۱۰۱ A 10

۱ ۱۰۱ B 20

۱ ۱۰۱ C 30

۱ ۱۰۱ D

۲ ۱۰۲ A 40

۲ ۱۰۲ B

۲ ۱۰۲ C 50

۲ ۱۰۲ D

۳ ۱۰۳ A 60

۳ ۱۰۳ B 70

۳ ۱۰۳ C 80

ID CUSTOMER_ID PRO QUANTITY

———- ———– — ———-

۳ ۱۰۳ D 90

۴ ۱۰۴ A 100

۴ ۱۰۴ B

۴ ۱۰۴ C

۴ ۱۰۴ D

۱۶ rows selected.

SQL>

0 پاسخ

دیدگاه خود را ثبت کنید

تمایل دارید در گفتگوها شرکت کنید؟
در گفتگو ها شرکت کنید.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *