如果以交叉表格式显示,则商业智能查询返回的数据通常是最有用的。SELECT语句的pivot_。数据透视是数据仓库中的一项关键技术。在其中,您可以将多行输入转换为数据仓库中较少且通常较宽的行。进行数据透视时,将为数据透视列值列表中的每个项应用聚合运算符。透视列不能包含任意表达式。如果需要对表达式进行透视,则应在透视操作之前在视图中对表达式进行别名。基本语法如下:

SELECT ....
FROM <table-expr>
PIVOT
(
aggregate-function(<column>) AS <alias>
FOR <pivot-column> IN (<value1>, <value2>,..., <valuen>)
) AS <alias>
WHERE .....

pivot_clause

PIVOT
( aggregate_function ( expr ) [[AS] alias ]
[, aggregate_function ( expr ) [[AS] alias ] ]...
FOR { column
| ( column [, column]... )
}
IN ( { { { expr
| ( expr [, expr]... )
} [ [ AS] alias]
}...
}
)
)

pivot_clause允许编写将行旋转为列的交叉表格查询,在旋转过程中聚合数据。透视操作的输出通常包括比起始数据集更多的列和更少的行。pivot_clause执行以下步骤:

  1. pivot_clause计算在子句开头指定的聚合函数。聚合函数必须指定一个GROUPBY子句以返回多个值,但pivot_clause不包含显式的GROUT BY子句。相反,pivot_clause执行一个隐式的groupby。隐式分组基于pivot_in_clause。如果指定了多个聚合函数,则必须至少为其中一个聚合函数以外的所有聚合函数提供别名。
  2. 在步骤 1 中计算的分组列和聚合值配置为生成以下跨表格输出:
  3. pivot_clause中未提及的所有隐式分组列,然后;
  4. pivot_in_clause中的值相对应的新列。将每个聚合值转换为交叉表中的适当新列。数据库为每个新列生成一个名称。如果未为聚合函数提供别名,则数据库将使用每个透视列值作为聚合值转换到的每个新列的名称。如果为聚合函数提供别名,则数据库将通过连接透视列名、下划线字符(_)和聚合函数别名,为聚合值转换到的每个新列生成名称。

创建用于透视示例的数据

创建用作基础的score_view视图,以说明透视的用法。

create or replace view score_view
(year, student, subject, score) as
values ('2020', '张三', '语文', 76),
('2020', '张三', '化学', 83),
('2020', '张三', '物理', 69),
('2020', '张三', '数学', 49),
('2020', '张三', '英语', 63),
('2020', '李四', '语文', 48),
('2020', '李四', '化学', 48),
('2020', '李四', '物理', 77),
('2020', '李四', '英语', 38),
('2020', '王五', '语文', 88),
('2020', '王五', '物理', 45),
('2020', '王五', '数学', 92),
('2020', '王五', '英语', 56),
('2021', '张三', '语文', 55),
('2021', '张三', '化学', 73),
('2021', '张三', '物理', 87),
('2021', '张三', '数学', 41),
('2021', '张三', '英语', 52),
('2021', '李四', '语文', 87),
('2021', '李四', '化学', 91),
('2021', '李四', '物理', 39),
('2021', '李四', '英语', 54),
('2021', '王五', '语文', 80),
('2021', '王五', '物理', 70),
('2021', '王五', '数学', 46),
('2021', '王五', '英语', 29); create or replace view subject_view (sn, subject) as
values (1, '语文'),
(2, '化学'),
(3, '物理'),
(4, '数学'),
(5, '英语'); create or replace view student_view (sn, student) as
values (1, '张三'),
(2, '李四'),
(3, '王五');

透视示例

下面的语句说明了如所述创建的视图。

SELECT *
FROM
(SELECT student, subject, score
FROM score_view
) S PIVOT (SUM(score)
FOR subject IN ( '语文' as "语文",
'化学' as "化学",
'物理' as "物理",
'数学' as "数学",
'英语' as "英语"))
ORDER BY student; STUD 语文 化学 物理 数学 英语
---- ---------- ---------- ---------- ---------- ----------
李四 135 139 116 92
王五 168 115 138 85
张三 131 156 156 90 115

在多列上透视

可以在多个列上旋转。

SELECT *
FROM score_view PIVOT (SUM(score)
FOR (subject,year) IN
(
('语文','2020') as "语文_2020",
('化学','2020') as "化学_2020",
('物理','2020') as "物理_2020",
('数学','2020') as "数学_2020",
('英语','2020') as "英语_2020",
('语文','2021') as "语文_2021",
('化学','2021') as "化学_2021",
('物理','2021') as "物理_2021",
('数学','2021') as "数学_2021",
('英语','2021') as "英语_2021")
)
ORDER BY student; STUD 语文_2020 化学_2020 物理_2020 数学_2020 英语_2020 语文_2021 化学_2021 物理_2021 数学_2021 英语_2021
---- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
李四 48 48 77 38 87 91 39 54
王五 88 45 92 56 80 70 46 29
张三 76 83 69 49 63 55 73 87 41 52

请注意,此示例指定了一个多列IN_LIST,其列标题设计为与IN_LIST成员匹配。

透视:多个聚合

可以使用多个聚合进行透视。

SELECT *
FROM (SELECT student, subject, score
FROM score_view) S PIVOT (SUM(score) AS sum,
AVG(score) AS avg
FOR subject IN ('语文',
'化学',
'物理',
'数学',
'英语')
)
ORDER BY student; STUD '语文'_SUM '语文'_AVG '化学'_SUM '化学'_AVG '物理'_SUM '物理'_AVG '数学'_SUM '数学'_AVG '英语'_SUM '英语'_AVG
---- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
李四 135 67.5 139 69.5 116 58 92 46
王五 168 84 115 57.5 138 69 85 42.5
张三 131 65.5 156 78 156 78 90 45 115 57.5

FOR subject In 不支持子查询。

SELECT *
FROM (SELECT student, subject, score
FROM score_view) S PIVOT (SUM(score) AS sum,
AVG(score) AS avg
FOR subject IN ( select subject from subject_view)
)
ORDER BY student; 第 5 行出现错误:
ORA-00936: 缺失表达式

请注意,查询通过连接聚合列的轴值、下划线字符(_)和别名来创建列标题。

区分 PIVOT 生成的空值和源数据中的空值

您可以区分使用PIVOT生成的空值和源数据中存在的空值。以下示例说明了PIVOT生成的空值。

数据准备:

STUD SUBJ      SCORE
---- ---- ----------
张三 语文 76
张三 物理
张三 数学 49
李四 语文 48
王五 语文 10
王五 语文 65
王五 物理 45 已选择 6 行。

查询结果:


SELECT *
FROM score1_view
PIVOT
( SUM(score) as sum, SUM(score1) as sum1,COUNT(*) AS cnt
FOR subject IN ('语文','物理','数学')
)
ORDER BY student; STUD 语文_SUM 语文_CNT 物理_SUM 物理_CNT 数学_SUM 数学_CNT
---- ---------- ---------- ---------- ---------- ---------- ----------
李四 48 1 0 0
王五 75 2 45 1 0
张三 76 1 1 49 1

从结果中,知道对于 “王五”,“语文“有2个成绩行,”物理“和”数学“有1个成绩行;对于”张三“,“语文“”物理“和”数学“有1个成绩行;对于”李四“,“语文“有1个成绩行,”物理“和”数学“没有成绩行。因此,在结果中,可以确定"张三"的”物理“NULL值来自原始表中度量值为NULL的行,而”李四“的”物理“NULL值,是因为原始表中没有行。

使用存储过程实现动态透视查询

交叉表格式的列,需要显性定义,如果 PIVOT_IN_CLAUSE 的值是不确定,而且希望能将全部数据旋转成列,所以需要拼接动态查询SQL脚本。

create or replace procedure proc_pivot(text, text)
language plsql
as
$$
declare
v_invalues text;
v_sql text;
begin
v_sql := $1;
v_sql := regexp_replace(v_sql, '(?i) pivot_in_values ', ' %s ');
execute $2 into v_invalues;
v_sql := format(v_sql, v_invalues);
call proc_dynamicsql(v_sql);
end;
$$
; call proc_pivot($$
SELECT *
FROM (SELECT student, subject, score
FROM score_view
) S PIVoT (SUM(score)
FOR subject IN ( pivot_in_values ))
ORDER BY student
$$,
$$select string_agg(distinct format('%L', subject), ',') from subject_view$$); student | 化学 | 数学 | 物理 | 英语 | 语文
---------+------+------+------+------+------
李四 | 139 | | 116 | 92 | 135
王五 | | 138 | 115 | 85 | 168
张三 | 156 | 90 | 156 | 115 | 131
(3 rows) call proc_pivot($$
SELECT *
FROM score_view PIVOT (SUM(score)
FOR (subject,year) IN ( pivot_in_values )
)
ORDER BY student
$$,
$$ select string_agg(distinct format('(%L,%L)', subject,year), ',') from subject_view,(values (2020),(2021)) v(year)
$$); student | 化学_2020 | 化学_2021 | 数学_2020 | 数学_2021 | 物理_2020 | 物理_2021 | 英语_2020 | 英语_2021 | 语文_2020 | 语文_2021
---------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------
李四 | 48 | 91 | | | 77 | 39 | 38 | 54 | 48 | 87
王五 | | | 92 | 46 | 45 | 70 | 56 | 29 | 88 | 80
张三 | 83 | 73 | 49 | 41 | 69 | 87 | 63 | 52 | 76 | 55
(3 rows)

存储过程proc_pivot的第一个参数是透视查询脚本,第二个参数是获取透视数据列的子查询脚本。透视查询脚本,其中 pivot_in_values 是关键字,将被透视数据列子查询结果替换。

透视数据列的子查询,需要与pivot-column的模式匹配。如果是多列,则必须增加括号,用以匹配pivot_for_clause的数据列。

支持动态查询结果的存储过程脚本

支持20个并行执行动态查询,而且不保留临时视图。

CREATE OR REPLACE PROCEDURE proc_dynamicsql(text)
language plsql
AS
$$
declare
v_viewname text;
begin
v_viewname := 'view_dynamicsql$'; --prefix
for i in 1..20 -- try 20 times
loop
begin
v_viewname := v_viewname || (random() * 20)::int::text;
execute format('create view %I as %s', v_viewname, $1);
exit;
exception
when others then
if i = 20 then
rollback;
return;
end if;
end ;
end loop;
-- parallel 20
case v_viewname
when 'view_dynamicsql$0' then select * from view_dynamicsql$0;
when 'view_dynamicsql$1' then select * from view_dynamicsql$1;
when 'view_dynamicsql$2' then select * from view_dynamicsql$2;
when 'view_dynamicsql$3' then select * from view_dynamicsql$3;
when 'view_dynamicsql$4' then select * from view_dynamicsql$4;
when 'view_dynamicsql$5' then select * from view_dynamicsql$5;
when 'view_dynamicsql$6' then select * from view_dynamicsql$6;
when 'view_dynamicsql$7' then select * from view_dynamicsql$7;
when 'view_dynamicsql$8' then select * from view_dynamicsql$8;
when 'view_dynamicsql$9' then select * from view_dynamicsql$9;
when 'view_dynamicsql$10' then select * from view_dynamicsql$10;
when 'view_dynamicsql$11' then select * from view_dynamicsql$11;
when 'view_dynamicsql$12' then select * from view_dynamicsql$12;
when 'view_dynamicsql$13' then select * from view_dynamicsql$13;
when 'view_dynamicsql$14' then select * from view_dynamicsql$14;
when 'view_dynamicsql$15' then select * from view_dynamicsql$15;
when 'view_dynamicsql$16' then select * from view_dynamicsql$16;
when 'view_dynamicsql$17' then select * from view_dynamicsql$17;
when 'view_dynamicsql$18' then select * from view_dynamicsql$18;
when 'view_dynamicsql$19' then select * from view_dynamicsql$19;
when 'view_dynamicsql$20' then select * from view_dynamicsql$20;
else return;
end case;
rollback;
end;
$$;

KingbaseES行转列(PIVOT)的更多相关文章

  1. sql 行转列 PIVOT 列转行 UNPIVOT

    原文:sql 行转列 PIVOT 列转行 UNPIVOT 一: 现有表一(t_table1),想转为表二(t_table2)的格式. 表一: 年 公司 收入 2013 公司1 12 2013 公司2 ...

  2. sql的行转列(PIVOT)与列转行(UNPIVOT) webapi 跨域问题 Dapper 链式查询 扩展 T4 代码生成 Demo (抽奖程序)

    sql的行转列(PIVOT)与列转行(UNPIVOT)   在做数据统计的时候,行转列,列转行是经常碰到的问题.case when方式太麻烦了,而且可扩展性不强,可以使用 PIVOT,UNPIVOT比 ...

  3. sql的行转列(PIVOT)与列转行(UNPIVOT)

    在做数据统计的时候,行转列,列转行是经常碰到的问题.case when方式太麻烦了,而且可扩展性不强,可以使用 PIVOT,UNPIVOT比较快速实现行转列,列转行,而且可扩展性强 一.行转列 1.测 ...

  4. sql server 行转列 Pivot UnPivot

    SQL Server中行列转换 Pivot UnPivot 本文转自:张志涛 原文地址: http://www.cnblogs.com/zhangzt/archive/2010/07/29/17878 ...

  5. SQL 行转列 PIVOT 学习示例

    CREATE TABLE [StudentScores] ( ), --学生姓名 ), --科目 [Score] FLOAT, --成绩 ) select * from [StudentScores] ...

  6. Oracle 行转列pivot 、列转行unpivot 的Sql语句总结

    这个比较简单,用||或concat函数可以实现 select concat(id,username) str from app_user select id||username str from ap ...

  7. SQL行转列(PIVOT)与列转行(UNPIVOT)简明方法

    原文地址:https://www.cnblogs.com/linJie1930906722/p/6036714.html 在做数据统计的时候,行转列,列转行是经常碰到的问题.case when方式太麻 ...

  8. 动态行转列 pivot实现

    declare @sql varchar(8000)    begin              set @sql=''  --初始化变量@sql              select  @sql= ...

  9. 行变列 pivot

    SELECT p.City , [临时] , [会员] , VIPFROM ( SELECT c.CustomerID , c.City , CASE WHEN COUNT(o.OrderID) &l ...

随机推荐

  1. javaweb_Http学习

    1. 什么是HTTP? HTTP(超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上. 文本:html,字符串,~... 超文本:图片,音乐,视频,定位,地图..... 默认端口:80 ...

  2. 关于Vue的几个实用知识点(持续更新中……)

    前言 排名不分先后,按自己习惯来的. 一.provide.inject 高级组件 总述: provide在父组件中定义,inject 在子孙组件中定义. provide:选项应该是一个对象或返回一个对 ...

  3. CMU15445 之 Project#0 - C++ Primer 详解

    前言 这个实验主要用来测试大家对现代 C++ 的掌握程度,实验要求如下: 简单翻译一下上述要求,就是我们需要实现定义在 src/include/primer/p0_starter.h 中的三个类 Ma ...

  4. linux web漏洞扫描arachni

    1. 下载arachni https://www.arachni-scanner.com/download/下载Linux x86 64bit 2. 上次解压直接使用 tar xzf arachni- ...

  5. docker安装报错failure: repodata/repomd.xml from mirrors.aliyun.com_docker-ce_linux_centos_docker-ce.pro

    1.进入 /etc/yum.repos.d 目录下,将所有有关 docker 的 repo 全部删掉 2.重新添加镜像 sudo yum-config-manager --add-repo https ...

  6. NC16430 [NOIP2016]蚯蚓

    NC16430 [NOIP2016]蚯蚓 题目 题目描述 本题中,我们将用符号 \(\lfloor c \rfloor\) 表示对 c 向下取整,例如:\(\lfloor 3.0 \rfloor = ...

  7. 基于.NetCore开发博客项目 StarBlog - (15) 生成随机尺寸图片

    系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...

  8. Python语法糖,提升编程幸福感!!!

    转载请注明出处️ 作者:测试蔡坨坨 原文链接:caituotuo.top/a52bc938.html 大家好,我是测试蔡坨坨. 今天,我们来盘点一下Python中的那些语法糖. 什么是语法糖?语法糖不 ...

  9. java---数组(重点概念)

    一.什么是数组 程序=算法+数据结构 数据结构:把数据按照某种特定的结构保存,设计一个合理的数据是解决问题的关键: 数组:是一种用于存储多个相同类型数据类型 的存储模型: 数组的特定结构:相同类型组成 ...

  10. Solution -「线段树」题目集合

    T1 无聊的数列 来自:Link flag 帖先从水题入手. 首先分析题目,它是以等差数列为原型进行的修改.等差数列一大性质就是其差分数列的值除第一项以外均相等. 于是不难想到使用差分数列进行维护. ...