Oracle11g 行列转换函数PIVOT and UNPIVOT

作为Oracle开发工程师,推荐大伙看看

PIVOT and UNPIVOT Operators in Oracle Database 11g Release 1

This article shows how to use the new PIVOT and UNPIVOT operators in 11g, as well as giving a pre-11g solution to the same problems.

  • PIVOT
  • UNPIVOT

Related articles.

PIVOT

The PIVOT operator takes data in separate rows, aggregates it and converts it into columns. To see the PIVOT operator in action we need to create a test table.

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;

So our test data starts off looking like this.

SELECT * FROM pivot_test;

ID CUSTOMER_ID PRODU   QUANTITY

---------- ----------- ----- ----------

1           1 A             10

2           1 B             20

3           1 C             30

4           2 A             40

5           2 C             50

6           3 A             60

7           3 B             70

8           3 C             80

9           3 D             90

10           4 A            100

10 rows selected.

SQL>

In its basic form the PIVOT operator is quite limited. We are forced to list the required values to PIVOT using the IN clause.

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

-------------- -------------- --------------

210             90            160

1 row selected.

SQL>

If we want to break it down by customer, we simply include the CUSTOMER_ID column in the initial select list.

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

----------- -------------- -------------- --------------

1             10             20             30

2             40                            50

3             60             70             80

4            100

4 rows selected.

SQL>

Prior to 11g we could accomplish a similar result using the DECODE function combined with aggregate functions.

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

-------------- -------------- --------------

210             90            160

1 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

----------- -------------- -------------- --------------

1             10             20             30

2             40              0             50

3             60             70             80

4            100              0              0

4 rows selected.

SQL>

Adding the XML keyword to the PIVOT operator allows us to convert the generated pivot results to XML format. It also makes the PIVOT a little more flexible, allowing us to replace the hard coded IN clause with a subquery, or the ANY wildcard.

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>

1 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>

1 row selected.

SQL>

Once again, the results can be broken down by customer, with each customers XML presented as a separate row.

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

----------------------------------------------------------------------------------------------------

1

<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>

2

<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>

3

<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

----------------------------------------------------------------------------------------------------

4

<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>

4 rows selected.

SQL>

UNPIVOT

The UNPIVOT operator converts column-based data into separate rows. To see the UNPIVOT operator in action we need to create a test table.

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;

So our test data starts off looking like this.

SELECT * FROM unpivot_test;

ID CUSTOMER_ID PRODUCT_CODE_A PRODUCT_CODE_B PRODUCT_CODE_C PRODUCT_CODE_D

---------- ----------- -------------- -------------- -------------- --------------

1         101             10             20             30

2         102             40                            50

3         103             60             70             80             90

4         104            100

4 rows selected.

SQL>

The UNPIVOT operator converts this column-based data into individual rows.

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

---------- ----------- - ----------

1         101 A         10

1         101 B         20

1         101 C         30

2         102 A         40

2         102 C         50

3         103 A         60

3         103 B         70

3         103 C         80

3         103 D         90

4         104 A        100

10 rows selected.

SQL>

There are several things to note about the query:

  • The required column names, in this case QUANTITY and PRODUCT_CODE, are define in the UNPIVOT clause. These can be set to any name not currently in the driving table.
  • The columns to be unpivoted must be named in the IN clause.
  • The PRODUCT_CODE value will match the column name it is derived from, unless you alias it to another value.
  • By default the EXCLUDE NULLS clause is used. To override the default behaviour use the INCLUDE NULLS clause.

The following query shows the inclusion of the INCLUDE NULLS clause.

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

---------- ----------- - ----------

1         101 A         10

1         101 B         20

1         101 C         30

1         101 D

2         102 A         40

2         102 B

2         102 C         50

2         102 D

3         103 A         60

3         103 B         70

3         103 C         80

ID CUSTOMER_ID P   QUANTITY

---------- ----------- - ----------

3         103 D         90

4         104 A        100

4         104 B

4         104 C

4         104 D

16 rows selected.

SQL>

Prior to 11g, we can get the same result using the DECODE function and a pivot table with the correct number of rows. In the following example we use the CONNECT BY clause in a query from dual to generate the correct number of rows for the unpivot operation.

SELECT id,

customer_id,

DECODE(unpivot_row, 1, ‘A‘,

2, ‘B‘,

3, ‘C‘,

4, ‘D‘,

‘N/A‘) AS product_code,

DECODE(unpivot_row, 1, product_code_a,

2, product_code_b,

3, product_code_c,

4, 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

---------- ----------- --- ----------

1         101 A           10

1         101 B           20

1         101 C           30

1         101 D

2         102 A           40

2         102 B

2         102 C           50

2         102 D

3         103 A           60

3         103 B           70

3         103 C           80

ID CUSTOMER_ID PRO   QUANTITY

---------- ----------- --- ----------

3         103 D           90

4         104 A          100

4         104 B

4         104 C

4         104 D

16 rows selected.

SQL>

原文地址:https://www.cnblogs.com/kingwei55555/p/10551272.html

时间: 2024-10-13 12:59:34

Oracle11g 行列转换函数PIVOT and UNPIVOT的相关文章

行列转换小结 Pivot ,Unpivot (转,改)

行专列 Pivot 1)SQL 2000版本 静态 SELECT ID , SUM(CASE Code WHEN 'Item1' THEN Value ELSE 0 END) AS Item1 , SUM(CASE Code WHEN 'Item2' THEN Value ELSE 0 END) AS Item2 , SUM(CASE Code WHEN 'Item3' THEN Value ELSE 0 END) AS Item3 FROM RowToCol GROUP BY ID --或者用

oracle行列转换函数的使用

racle 10g wmsys.wm_concat行列转换函数的使用: 首先让我们来看看这个神奇的函数wm_concat(列名),该函数可以把列值以","号分隔起来,并显示成一行,接下来上例子,看看这个神奇的函数如何应用 1.把结果按分组用逗号分割,以一行打印出来.(如果需要换其它的可以用replace函数:replace(wm_concat(name),',','|')) select t.u_id, wmsys.wm_concat(t.goods), wmsys.wm_concat

行列转换函数

PIVOT函数与UNPIVOT函数的运用 PIVOT用于将行转为列,完整语法如下:TABLE_SOURCEPIVOT(聚合函数(value_column)FOR pivot_columnIN(<column_list>)) UNPIVOT用于将列转为行,完整语法如下:完整语法:TABLE_SOURCE UNPIVOT( value_column FOR pivot_column IN(<column_list>)) 以上语法可以理解为value_column字段与pivot_col

oracle高级SQL(四)--SQL行列转换专题2

[上一专题]  行列转换1  -- PIVOT与UNPIVOT函数的介绍 实现案例 1001 lufei 1001 shanzhi 1001 namei 1001 qiaoba 实现效果如下: 1001 lufei,shanzhi,namei,qiaoba 典型的行列转换:实现这种方法有很多. 其中oracle11g之后提供了listagg函数;用来实现上面的效果最好不过了:我们来看下listagg语法 listagg函数的语法结构如下: >listagg( [,]) within group

SQL Fundamentals: 子查询 || 行列转换(PIVOT,UNPIVOT,DECODE),设置数据层次(LEVEL...CONNECT BY)

SQL Fundamentals || Oracle SQL语言 子查询(基础) 1.认识子查询 2.WHERE子句中使用子查询 3.在HAVING子句中使用子查询 4.在FROM子句中使用子查询 5.在SELECT子句中使用子查询 6.WITH子句 子查询(进阶) 7.分析函数 8.行列转换 9.设置数据层次 八.行列转换 pivot和unpivot函数是Oracle 11g增加的新函数,利用此函数可以实现行列转换操作 按照原始方式实现,使用通用函数中的DECODE()函数 列字段的处理 SQ

pivot 与 unpivot函数

pivot 与 unpivot函数pivot 与 unpivot 函数是SQL05新提供的2个函数 灰常灰常的实用 ------------------------------------------------------------------------------ pivot函数: create table test(id int,name varchar(20),quarter int,profile int)insert into test values(1,'a',1,1000)i

SQL行列转换6种方法

在进行报表开发时,很多时候会遇到行列转换操作,很对开发人员针对于SQL级别行列转换操作一直不甚理解,今天正好抽空对其进行了一些简单的总结.这里主要列举3种可以实现SQL行列转换的方法,包括通用SQL解法以及Oracle支持解法. 一.测试数据 测试表依旧采用Oracle经典的scott模式下的dept表和emp表,结构如下: DEPT: create table DEPT ( DEPTNO NUMBER(2) not null, DNAME VARCHAR2(14), LOC VARCHAR2(

sql pivot、unpivot和partition by用法

原文:sql pivot.unpivot和partition by用法 演示脚本 IF not exists(SELECT 1 from sys.sysobjects where name = 'Student' AND type = 'U') BEGIN CREATE table Student( ID int identity primary key, ClassID int default 0 , --班级ID CourseName nvarchar(20) , --课程 Name nva

SQL Server 使用 Pivot 和 UnPivot 实现行列转换

对于行列转换的数据,通常也就是在做报表的时候用的比较多,之前也零零散散的看了一些,今天就来总结一下. 先创建一个用于演示的临时表: create table #temp ( 年份 nvarchar(10) null, 月份 nvarchar(10) null, 数量 int null ) insert into #temp(年份,月份,数量) select '2015','1','5645' union select '2015','2','1234' union select '2015','