oracle中通过decode实现行变列的二维表统计展示

testa

ID VARCHAR2(20)
USERNAME VARCHAR2(20)
STATUS VARCHAR2(20)

测试数据:

1 123  协商同意
2 rsr 未协商同意
3 rsr 协商同意
5 123 暂停
8 rsr 暂停
11 123  延迟
22 123  延迟
12 rsr  延迟

sql:

select username

,count(decode(status,'协商同意',status))  协商同意
,count(decode(status,'未协商同意',status))  未协商同意
,count(decode(status,'暂停',status)) 暂停
,count(decode(status,'延迟',status))   延迟

from testa group by username

展示效果:
这里写图片描述

感触:oracle很强,通过sql可以简单的实现二维的统计信息,而无需改变表结构.

这里涉及decode用法:
这里写图片描述

我一般都只用前三个字段decode(字段,比较值1,返回值)


Oracle中的二维表查询函数

对于日常的报表统计,在oracle中的group by子句产生的查询往往不够直观,还需要excel的透视图才能产生二维报表.虽然在Oracle 11G中实现了这个功能,但我想鉴于我们目前还是10G的数据库.写这么一个函数还是有必要的.
源代码已经在下文中,直接在运行代码就可以得到函数GET_TWO_DIMENSIONAL_QUERY.
函数构成:该函数有3个参数,第一个参数是表名或者查询语句,第二个参数是X轴字段(仅允许单个字段),第三个参数是Y轴字段(允许多个字段,字段之间使用,分隔)
效果展示:
创建测试表:

create table TEST (name varchar2(255) ,sex varchar2(255),expenseability varchar2(255),district varchar2(255));
insert into TEST values ('张三','男','高消费','浦东新区');
insert into TEST values ('王强','男','高消费','浦东新区');
insert into TEST values ('马骏','男','中高消费','徐汇区');
insert into TEST values ('可乐','女','中等消费','闵行区');
commit;

得到表:

NAME SEX EXPENSEABILITY DISTRICT
张三 高消费 浦东新区
王强 高消费 浦东新区
马骏 中高消费 徐汇区
可乐 中等消费 闵行区

执行查询函数: select GET_TWO_DIMENSIONAL_QUERY('TEST','district','sex') from dual 后得到查询反馈:

select sex,expenseability,sum (case when district='闵行区' then num else 0 end) as "闵行区",
sum (case when district='徐汇区' then num else 0 end) as "徐汇区",
sum (case when district='浦东新区' then num else 0 end) as "浦东新区"
from (select district,sex,expenseability,count(*) num from (TEST) group by district,sex,expenseability)
group by sex,expenseability

执行查询反馈就可以得到二维报表:

扫描二维码关注公众号,回复: 1879258 查看本文章
SEX EXPENSEABILITY 闵行区 徐汇区 浦东新区
高消费 0 0 2
中等消费 1 0 0
中高消费 0 1 0

函数源码:

create or replace function GET_TWO_DIMENSIONAL_QUERY (TABLENAME in varchar2 ,P_X in varchar2 ,P_Y in varchar2) 
return clob is 
Result clob;
type curtype is ref cursor;
v_cur curtype;
v_BaseQuery varchar2(4000);
v_sqlstr varchar2(4000);
v_temp varchar2(4000);
begin
--获取group by 语句
v_BaseQuery:='(select '||P_X||','||P_Y||',count(*) num from ('||TABLENAME||') group by '||P_X||','||P_Y||')';
--选中Y轴字段
Result:='select '||P_Y||',';
--产生游标SQL
v_sqlstr :=' select distinct '||P_X||' from ('||v_BaseQuery||')';
--打开游标
open v_cur for v_sqlstr;
loop
fetch v_cur into v_temp;
exit when v_cur%notfound;

--判断值是否为空
if v_temp is null then
--产生X轴SQL
Result:=Result||'sum (case when '||P_X||' is null then num else 0 end) as "'||P_X||'为空'||'",';
Result:=Result||chr(13); 
else
Result:=Result||'sum (case when '||P_X||'='''||v_temp||''' then num else 0 end) as "'||v_temp||'",';
Result:=Result||chr(13);
end if;

end loop; 

--格式对齐
Result:=rtrim(Result,chr(13));
Result:=rtrim(Result,',');

Result:=Result||chr(13);
--将from字句与group by 子句加入 
Result:=Result||'from '||v_BaseQuery||''||chr(13)||'group by '||P_Y||' ';

return Result;
end;

其实只是个代码生成函数,不过做报表用用还是挺方便的 ^_^


按照行、列进行统计(按两个维度进行统计)

select * from u_md_dm.s_temp_import_d;

这里写图片描述

1、按照年和姓名来统计每个人每年的签到次数

select k.dates,sum(case when k.pro_d_name='张三' then k.times else 0 end) 张三,sum(case when k.pro_d_name='李四' then k.times else 0 end) 李四,sum(case when k.pro_d_name='王五' then k.times else 0 end) 王五 
from (
select substr(pro_d_no,0,5) dates,pro_d_name,count(1) times from u_md_dm.s_temp_import_d group by substr(pro_d_no,0,5),pro_d_name) k
group by k.dates;

这里写图片描述

另:也可以用下面的语句实现:

with k as
(select substr(pro_d_no,0,5) dates,pro_d_name,count(1) times from u_md_dm.s_temp_import_d group by substr(pro_d_no,0,5),pro_d_name)
select 
k.dates,sum(case when k.pro_d_name='张三' then k.times else 0 end) 张三,sum(case when k.pro_d_name='李四' then k.times else 0 end) 李四,sum(case when k.pro_d_name='王五' then k.times else 0 end) 王五 
from k group by k.dates

猜你喜欢

转载自blog.csdn.net/wulex/article/details/80813662