思路简析:
1° 准备测试数据:
drop table t purge;
create table t(a varchar2(10), b varchar2(10));
insert into t values('a1','b1');
insert into t values('a1','b2');
commit;
2° 进行行列转换的数据一般是”某一列”存在重复冗余的数据,如:
select * from t;
表t的列A中值a1存在重复,可以将a1作为基准,对a1所在的两行的列B的数值b1和b2做行列转换,行转列
因为列B的取值范围有两个b1和b2,因此行列转换后会生成两列,即两行转两列
3° 生成新列:
select a, b,
case b when 'b1' then '第1个列值生成新第1列'
else null
end as b1,
case b when 'b2' then '第2个列值生成新第2列'
else null
end as b2
from t;
使用多个case函数对列B的列值进行匹配,将匹配到的相应列值转化成新列,行转列数据模式初显
4° case语法较为臃肿,使用decode函数进行改写:
select a, b,
decode(b,'b1','第1个列值生成新第1列',null) as b1,
decode(b,'b2','第2个列值生成新第2列',null) as b2
from t;
5° 我们已经将B列列值展开成多列,因此剔除B列展示,然后先查看展开生成的第一列,观察特点:
select a, -- b,
decode(b,'b1','第1个列值生成新第1列',null) as b1 -- ,
-- decode(b,'b2','第2个列值生成新第2列',null) as b2
from t;
此时不难发现,展开生成的第一列存在空值,意义不大,应该过滤掉,可以使用 where B1 is not null
但是该方法需要使用子查询,因为SQL执行顺序是先执行where后执行select
6° 另外一种方法是依据A列分组,对B1列进行聚合处理,因为B1是字符串,使用max或者min均可过滤掉空值:
select a, -- b,
min(decode(b,'b1','第1个列值生成新第1列',null)) as b1 -- ,
-- decode(b,'b2','第2个列值生成新第2列',null) as b2
from t
group by a;
7° 将所有展开列都依此处理,得出最后SQL:
select a, -- b,
min(decode(b,'b1','第1个列值生成新第1列',null)) as b1,
max(decode(b,'b2','第2个列值生成新第2列',null)) as b2
from t
group by a;
8° 简单总结:
字段值重复是行列转换的基础,如果不存在冗余数据列,则无法进行行列转换
行列转换的方法就是使用case或者decode对冗余数据列之外的其他列的列值进行展开
然后依据冗余数据列分组聚合,最后形成行列转换的功能
[TOC]