oracle中的行列转换(一 列转行 pivot)

时间:2021-08-02 00:47:10

在实际统计中,我们可能需要对统计的数据进行行列转换以达到我们想要的更便于分析查看对比的格式。例如:我们想要统计在一段时间(过去一年或一个月)所有客户在24小时的消费情况。对于结果我们更愿意让一行记录标识一个客户的24小时消费情况。下面我以oracle中的emp表为例,使用pivot列转行达到我们想要的效果。

select deptno, empjob, sum(sal) from emp group by deptno, empjob order by deptno, empjob

结果如下:

oracle中的行列转换(一 列转行 pivot)

显然这样的结果并不便于我们观察各部门各职位的总薪资。我们可以使用pivot来实现:

select * from 
(select deptno, empjob, sal from emp)
pivot(
sum(sal) for empjob in (
'PRESIDENT' as PRESIDENT,
'MANAGER' as MANAGER,
'ANALYST' as ANALYST,
'CLERK' as CLERK,
'SALESMAN' as SALESMAN
)
) order by deptno;

结果如下:
oracle中的行列转换(一 列转行 pivot)

我们可能不想自己手工输入empjob对应的值,可以使用plsql解决这个问题。

declare  
str1 varchar2(200);
str2 varchar2(500);
begin
select LISTAGG( empjob,''',''') within group (order by empjob) as str into str1 from (select empjob from emp group by empjob);

STR1 := ' '' '||str1 ||' '' ';
str2 := 'select * from
(select deptno, empjob, sal from emp)
pivot(
sum(sal) for empjob in (
'||str1||' ) ) order by deptno';
DBMS_OUTPUT.PUT_LINE('
str1:'||str1);
DBMS_OUTPUT.PUT_LINE('
str2'||str2);
end;

输出结果为:

str1:' ANALYST','CLERK','MANAGER','PRESIDENT','SALESMAN ' 
str2:select * from
(select deptno, empjob, sal from emp)
pivot(
sum(sal) for empjob in (
'ANALYST','CLERK','MANAGER','PRESIDENT','SALESMAN' ) ) order by deptno

注意:
str2执行后查询到的结果:

oracle中的行列转换(一 列转行 pivot)

注意:类名称可能并不是我们期望的,注意修改列名称。

这时候我们就可以根据业务逻辑需求修改plsql或者存储过程等,创建相应的表或者视图,将查询到的数据放到表或视图,方便我们以后使用。

上面的例子是只有sum(sal)这一列的值,现在我们要解决的问题是:汇总各部门各职位的薪资总和和职员人数。

select * from
(select deptno, empjob, sal from emp)
pivot(
sum(sal) as sal_sum, count(sal) as num for empjob in (
'PRESIDENT' as PRESIDENT,
'MANAGER' as MANAGER,
'ANALYST' as ANALYST,
'CLERK' as CLERK,
'SALESMAN' as SALESMAN ) ) order by deptno

结果如下:

oracle中的行列转换(一 列转行 pivot)