kingbase之pivot用法

一、PIVOT和UNPIVOT行列转换
PIVOT 和 UNPIVOT 是SELECT的一种扩展查询方式。 PIVOT 查询涉及将行置转换为列,或者使用 UNPIVOT 将列置转换为行,以交叉表格式生成结果。

PIVOT 操作为行转列,并在转换过程中聚合数据,新的列表示不同范围的聚合数据, PIVOT 操作的输出通常比初始数据行包含更多的列和更少的行。

UNPIVOT 是 PIVOT 的反操作,它是将多个列的内容合并到同一个列中,以多行形式展示。

关于输入结果有如下使用限制:

输入为一个查询或者子查询的结果集,当为一个子查询的时候,支持目标列的类型可以为列名、常量或者表达式,但是为常量或者表达式的时候必须使用别名,表达式中支持使用列名和常量进行计算,且子查询只支持单表为输入且不支持表使用别名。

1.1 PIVOT行转列
PIVOT 操作是将查询结果集进行行转列

SELECT select_list
FROM table_expression
[ PIVOT aggfunction FOR column... IN (('column_const','column_const'...) [AS alais], ....) ]

PIVOT 首先计算指定的聚合函数的值。通常聚合函数必须指定GROUP BY子句才能返回多个值,但是在PIVOT子句不包含显式的GROUP BY子句。在PIVOT子句执行隐式GROUP BY。
隐式GROUP BY是基于所有没有在PIVOT子句中引用的列,以及在在PIVOT的IN子句中指定的一组值。
根据指定的分组列和聚合值,生成的交叉表包含以下列:
所有没在PIVOT子句中引用的隐式分组列值。
以及与PIVOT的IN子句中的值对应的新列,每个聚合的值被转换到适当的新列中。 数据库将为每个新列生成一个名称:如果没有为聚合函数提供别名,则使用每个pivot列的值作为聚合函数转置到的每个新列的名称。如果为聚合函数提供别名,则连接PIVOT列名、下划线字符和聚合函数别名为每个新列生成的一个名称。
一个转换单列的例子:

select * from pivot_t1;
month |  name  | nums | other
-------+--------+------+-------
    1 | apple  | 1000 | a
    2 | apple  | 2000 | d
    3 | apple  | 4000 | a
    1 | orange |  400 | d
    2 | orange |  500 | b
    3 | orange |  500 | b
    1 | grape  | 3500 | c
    2 | grape  | 3500 | c
    3 | grape  | 3500 | c
(9 rows)

select * from  (select month,name,nums from pivot_t1)  pivot (sum(nums) for name in ('apple' as pingguo ,'orange' as juzi ,'grape' as putao));
month | pingguo | juzi | putao
-------+---------+------+-------
    1 |    1000 |  400 |  3500
    2 |    2000 |  500 |  3500
    3 |    4000 |  500 |  3500
(3 rows)

此例中将name列中的值转换为列并计算了他的聚合值生成一个新的结果集。
多列转换的的例子:
select * from (select month,name,nums,other from pivot_t1) pivot (sum(nums) for (name,other) in ( (‘apple’,‘a’), (‘orange’,‘b’) , (‘grape’,‘c’) , (‘apple’,‘d’) , (‘orange’,‘d’)));
month | apple_a | orange_b | grape_c | apple_d | orange_d
-------±--------±---------±--------±--------±---------
1 | 1000 | | 3500 | | 400
2 | | 500 | 3500 | 2000 |
3 | 4000 | 500 | 3500 | |
此例中将name列和other列中的值转换为列并计算了他的聚合值生成一个新的结果集。
1.2 UNPIVOT列转行
UNPIVOT是PIVOT的反操作,它是将列转换为行。

SELECT select_list
FROM table_expression
[ UNPIVOT new_column... FOR new_column... IN ((column,...) [AS alais], ....) ]

UNPIVOT 将列旋转为行,生成的交叉表中包含:未出现在UNPIVOT的IN子句中的所有列,以及存储参与转换字段列名的新列(FOR子句之后指定)和对应输出字段值的新列(FOR子句前指定)。
INCLUDE | EXCLUDE NULLS 子句提供了包括或排除空值行的选项。INCLUDE NULLS使unpivot操作包含null值的行;EXECLUDE NULLS将排除具有null值的行。如果省略此子句,则unpivot操作将排除null值。
FOR子句 此子句指定转换后的新字段名称,用于存放参与列转行的每个输出字段的列名。
IN子句 指定要参与行列转换的原始列表,指定名称将成为IN子句指定新列的输入数据(列转行的值列表)。可选AS子句允许输入数据列名映射到其他指定文字。
一个转换单列的例子:

select * from unpivot_t1;
id |  name  |  q1  |  q2  |  q3  |  q4
----+--------+------+------+------+------
1 | apple  | 1000 | 2000 | 3300 | 5000
2 | orange | 3000 | 3000 | 3200 | 1500
3 | banana | 2500 | 3500 | 2200 | 2500
4 | grape  | 1500 | 2500 | 1200 | 3500
(4 rows)

update unpivot_t1 set q4=NULL where id=4;
select id,name,jidu ,xiaoshou from unpivot_t1 unpivot include nulls (xiaoshou for jidu in (q1 as 'Q1',q2 as 'Q2',q3 as 'Q3',q4 as 'Q4')) order by id,jidu;
id |  name  | jidu | xiaoshou
----+--------+------+----------
1 | apple  | Q1   |     1000
1 | apple  | Q2   |     2000
1 | apple  | Q3   |     3300
1 | apple  | Q4   |     5000
2 | orange | Q1   |     3000
2 | orange | Q2   |     3000
2 | orange | Q3   |     3200
2 | orange | Q4   |     1500
3 | banana | Q1   |     2500
3 | banana | Q2   |     3500
3 | banana | Q3   |     2200
3 | banana | Q4   |     2500
4 | grape  | Q1   |     1500
4 | grape  | Q2   |     2500
4 | grape  | Q3   |     1200
4 | grape  | Q4   |
(16 rows)

多列转换的的例子:

select * from unpivot_t1 unpivot ((xiaoshou,xiaoshou2) for (jidu1,jidu2) in ((q1,q2),(q3,q4))) order by 1,2,3;
id |  name  | jidu1 | jidu2 | xiaoshou | xiaoshou2
----+--------+-------+-------+----------+-----------
1 | apple  | q1_q2 | q1_q2 |     1000 |      2000
1 | apple  | q3_q4 | q3_q4 |     3300 |      5000
2 | orange | q1_q2 | q1_q2 |     3000 |      3000
2 | orange | q3_q4 | q3_q4 |     3200 |      1500
3 | banana | q1_q2 | q1_q2 |     2500 |      3500
3 | banana | q3_q4 | q3_q4 |     2200 |      2500
4 | grape  | q1_q2 | q1_q2 |     1500 |      2500
4 | grape  | q3_q4 | q3_q4 |     1200 |
(8 rows)

二、pivot连续使用两次
最近在项目上碰到oracle->kingbase改造中视图里面使用了两次pivot
下面测试是否可以使用两次将第一次pivot的结果第二次pivot引用

pivot行转列测试连续使用两个pviot
20240731

---构建数据
drop table usr;
create table usr(
id int,
name varchar2(20),
score int,
class varchar2(20)
);

insert into usr values(1,'a',20,'math');
insert into usr values(1,'a',22,'phy');
insert into usr values(2,'b',23,'phy');
insert into usr values(3,'b',21,'math');
insert into usr values(2,'c',22,'phy');
insert into usr values(3,'c',24,'math');
insert into usr values(1,'d',25,'math');
insert into usr values(2,'d',23,'phy');

test=# select * from usr;
 id | name | score | class
----+------+-------+-------
  1 | a    |    20 | math
  1 | a    |    22 | phy
  2 | b    |    23 | phy
  3 | b    |    21 | math
  2 | c    |    22 | phy
  3 | c    |    24 | math
  1 | d    |    25 | math
  2 | d    |    23 | phy
(8 rows)


--执行报错SQL 错误 [0A000]: ERROR: We don't support pivot with sub-query which contains a '*' in it's targets.
select * from (
select * from usr  pivot(sum(score)for class in ('math','phy'))) pivot(sum(phy) for id in(1,2,3));

---可以执行
select * from (
select id,name,math,phy from usr  pivot(sum(score)for class in ('math','phy'))) pivot(sum(phy) for id in(1,2,3));

---问题出在这里:不可以使用*,要使用具体第一次pivot之后的字段

<in ('math','phy'))) pivot(sum(phy) for id in(1,2,3));
 name | math | 1  | 2  | 3
------+------+----+----+---
 a    |   20 | 22 |    |
 b    |   21 |    |    |
 b    |      |    | 23 |
 c    |   24 |    |    |
 c    |      |    | 22 |
 d    |   25 |    |    |
 d    |      |    | 23 |
(7 rows)


--构建新表查看字段
select *  into  table t3 from usr   pivot(sum(score)for class in ('math','phy'));
--查询结果
select * from t3;

 id | name | math | phy
----+------+------+-----
  1 | a    |   20 |  22
  1 | d    |   25 |
  2 | b    |      |  23
  2 | c    |      |  22
  2 | d    |      |  23
  3 | b    |   21 |
  3 | c    |   24 |
(7 rows)
最终需要的结果是
最终结果是
 name | math | 1  | 2  | 3
------+------+----+----+---
 a    |   20 | 22 |    |
 b    |   21 |    |    |
 b    |      |    | 23 |
 c    |   24 |    |    |
 c    |      |    | 22 |
 d    |   25 |    |    |
 d    |      |    | 23 |
(7 rows)
正确,可以使用两次,但是不支持嵌套*
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/927bb56293b041eba4042cc22cf60d35.png)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值