|
专门为不带汇总的行列转换写了一个
create or replace function
fsql2(v_tname varchar,tr varchar ,tc0 varchar,v_tcode varchar)
return varchar
is
tc varchar(4000);
sqlstr varchar(4000);
s1 varchar(4000);
s2 varchar(4000);
s3 varchar(4000);
s4 varchar(4000);
TYPE rc IS REF CURSOR;
TYPE nlist IS TABLE OF NUMBER;
TYPE vlist IS TABLE OF VARCHAR2(400);
rc1 rc;
g1 vList;
g2 vList;
g3 vList;
begin
tc:=' '||trim(tc0)||' ';
s1:='with t
as (select '||tr||','||replace(trim(tc),' ',',')||',count(*) cnt from '|| v_tname||' group by '||tr||','||replace(trim(tc),' ',',')||')';
sqlstr:='select l,substr(tc,instr(tc,'' '',1,l)+1,instr(tc,'' '',1,l+1)-instr(tc,'' '',1,l)-1) pos
from (select '''||tr||'''tr,'''||tc||''' from dual)t,(select level l from dual connect by level<=10)a where l<length(tc)-length(replace(tc,'' '',''''))';
sqlstr:=replace(sqlstr,'tc',''''||tc||'''');
s3:='select ''min(case when ''';
OPEN rc1 FOR sqlstr;
FETCH rc1 BULK COLLECT INTO g1, g2;
CLOSE rc1;
FOR i IN g1.FIRST ..g1.LAST-1
LOOP
if i>1 then
s2:=s2||',';
s3:=s3||''' and ''';
end if;
s2:=s2||'(select * from '||v_tcode||' where cname='''||g2(i)||''' and ccode is not null)'||chr(96+i)||chr(10); --拼凑where
--(a)sqlstr:=q'[select 'sum(case when '||a.cname||'='''||a.ccode||''' and '||b.cname||'='''||b.ccode||''' then cnt end)as c'|| a.cname2||b.cname2
--(b)sum(case when sex='M' and age='1' then cnt end)as c男1岁
s3:=s3||'||'||chr(96+i)||'.cname||''=''''''||'||chr(96+i)||'.ccode||'||'''''' ; --拼凑case when语句,拼出(a),运行得(b)
s4:=s4||case i when 1 then'c''||'else'||'end||chr(96+i)||'.cname2'; --拼凑别名
END LOOP;
sqlstr:=s3||''' then '||g2(g1.LAST)||' end) as '||s4||'
from '||replace(s2,'tc',''''||tc||'''');
s2:='';
s4:='SELECT cname,ccode,cname2 FROM '||v_tcode||' WHERE tname=:1 and cname=:2';
OPEN rc1 FOR s4 USING v_tname,tr;
FETCH rc1 BULK COLLECT INTO g1, g2,g3;
CLOSE rc1;
FOR i IN g1.FIRST ..g1.LAST
LOOP
if g1(i)=tr and g2(i)is null then
s2:='
,t1 as(select '||tr||' as '||g3(i)||chr(10);
end if;
END LOOP;
if s2 is null then
return 'error';
end if;
--return sqlstr;
OPEN rc1 FOR sqlstr;
FETCH rc1 BULK COLLECT INTO g1;
CLOSE rc1;
FOR i IN g1.FIRST ..g1.LAST
LOOP
s2:=s2||','||g1(i)||chr(10);
END LOOP;
s3:='group by '||tr;
return s1||s2||'from t '||s3||')
select * from t1';
end;
/
create table faq(ID varchar(10),NAME varchar(10),VALUE varchar(10));
insert into faq select * from (
select'1'id,'a1'name,'x1'value from dual union all
select'1','a2','x2'from dual union all
select'2','b1','y1'from dual union all
select'2','b2','y2'from dual union all
select'2','b3','y3'from dual);
commit;
insert into eav values('FAQ','ID',NULL,'ID');
insert into eav select 'FAQ','ID',ID,ID from dual,(select unique id from faq);
insert into eav values('FAQ','NAME',NULL,'NAME');
insert into eav select 'FAQ','NAME',NAME,NAME from dual,(select unique NAME from faq);
insert into eav values('FAQ','VALUE',NULL,'VALUE');
insert into eav select 'FAQ','VALUE',VALUE,VALUE from dual,(select unique VALUE from faq);
commit;
SQL> select fsql2('FAQ','NAME','ID VALUE','eav')from dual;
FSQL2('FAQ','NAME','IDVALUE','EAV')
-------------------------------------------------------------------------------
with t
as (select NAME,ID,VALUE,count(*) cnt from FAQ group by NAME,ID,VALUE)
,t1 as(select NAME as NAME
,min(case when ID='1' then VALUE end) as c1
,min(case when ID='2' then VALUE end) as c2
from t group by NAME)
select * from t1
已用时间: 00: 00: 00.01
SQL> with t
2 as (select NAME,ID,VALUE,count(*) cnt from FAQ group by NAME,ID,VALUE)
3 ,t1 as(select NAME as NAME
4 ,min(case when ID='1' then VALUE end) as c1
5 ,min(case when ID='2' then VALUE end) as c2
6 from t group by NAME)
7 select * from t1;
NAME C1 C2
---------- ---------- ----------
a1 x1
b2 y2
a2 x2
b1 y1
b3 y3
|
|
|