|
第一个勉强能用的版本,
只能在10g以上用,因为单引号的问题
行方向只支持1个group by
列方向只支持2个group by
- create table eav(tname varchar(20),cname varchar(20),ccode varchar(20),cname2 varchar(40));
- insert into eav select 'tren',NULL,NULL,'人口表' from dual;
- insert into eav select 'tren','sex',NULL,'性别' from dual;
- insert into eav select 'tren','sex','M','男' from dual;
- insert into eav select 'tren','sex','F','女' from dual;
- insert into eav select 'tren','age',NULL,'年龄' from dual;
- insert into eav select 'tren','age','1','1岁' from dual;
- insert into eav select 'tren','age','2','2岁' from dual;
- insert into eav select 'tren','region',NULL,'地区' from dual;
- insert into eav select 'tren','region','1','北京' from dual;
- insert into eav select 'tren','region','2','天津' from dual;
- commit;
- create table tren(rn number(10,0),sex varchar(1),age varchar(2),region varchar(3));
- insert into tren select level,
- decode(mod(abs(dbms_random.random),2),0,'M','F'),
- mod(abs(dbms_random.random),2)+1,
- mod(abs(dbms_random.random),2)+1 from dual connect by level<=1000;
- commit;
- create or replace function
- fsqlgen(v_tname varchar,v_gc1 varchar ,v_gc2 varchar,v_gc3 varchar,v_tcode varchar)
- return varchar
- is
- 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
- s1:='with t
- as (select '||v_gc1||','||v_gc2||','||v_gc3||',count(*)cnt from '||v_tname||' group by '||v_gc1||','||v_gc2||','||v_gc3||')';
- sqlstr:='SELECT cname,ccode,cname2 FROM '||v_tcode||' WHERE tname=:1 and cname=:2';
- OPEN rc1 FOR sqlstr USING v_tname,v_gc1;
- FETCH rc1 BULK COLLECT INTO g1, g2,g3;
- CLOSE rc1;
- FOR i IN g1.FIRST ..g1.LAST
- LOOP
- if g1(i)=v_gc1 and g2(i)is null then
- s2:='
- ,t1 as(select '||v_gc1||' as '||g3(i)||chr(10);
- end if;
- END LOOP;
- if s2 is null then
- return 'error';
- end if;
- sqlstr:=q'[select 'sum(case when '||a.cname||'='''||a.ccode||''' and '||b.cname||'='''||b.ccode||''' then cnt end)as c'|| a.cname2||b.cname2
- from
- (select * from ]'||v_tcode||q'[ where cname=']'||v_gc2||q'[' and ccode is not null)a,
- (select * from ]'||v_tcode||q'[ where cname=']'||v_gc3||q'[' and ccode is not null)b
- ]' ;
- 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 '||v_gc1;
- return s1||s2||'from t '||s3||')
- select * from t1';
- end;
- /
复制代码
SQL> select fsqlgen('tren','region','sex','age','eav') from dual;
FSQLGEN('TREN','REGION','SEX','AGE','EAV')
-------------------------------------------------------------------------------------------------------------------------
with t
as (select region,sex,age,count(*)cnt from tren group by region,sex,age)
,t1 as(select region as 地区
,sum(case when sex='M' and age='1' then cnt end)as c男1岁
,sum(case when sex='F' and age='1' then cnt end)as c女1岁
,sum(case when sex='M' and age='2' then cnt end)as c男2岁
,sum(case when sex='F' and age='2' then cnt end)as c女2岁
from t group by region)
select * from t1
SQL> with t
2 as (select region,sex,age,count(*)cnt from tren group by region,sex,age)
3 ,t1 as(select region as 地区
4 ,sum(case when sex='M' and age='1' then cnt end)as c男1岁
5 ,sum(case when sex='F' and age='1' then cnt end)as c女1岁
6 ,sum(case when sex='M' and age='2' then cnt end)as c男2岁
7 ,sum(case when sex='F' and age='2' then cnt end)as c女2岁
8 from t group by region)
9 select * from t1;
地 C男1岁 C女1岁 C男2岁 C女2岁
--- ---------- ---------- ---------- ----------
1 126 102 136 123
2 142 125 124 122
SQL> select fsqlgen('tren','sex','region','age','eav') from dual;
FSQLGEN('TREN','SEX','REGION','AGE','EAV')
-------------------------------------------------------------------------------------------------------------------------
with t
as (select sex,region,age,count(*)cnt from tren group by sex,region,age)
,t1 as(select sex as 性别
,sum(case when region='1' and age='1' then cnt end)as c北京1岁
,sum(case when region='1' and age='2' then cnt end)as c北京2岁
,sum(case when region='2' and age='1' then cnt end)as c天津1岁
,sum(case when region='2' and age='2' then cnt end)as c天津2岁
from t group by sex)
select * from t1
SQL> with t
2 as (select sex,region,age,count(*)cnt from tren group by sex,region,age)
3 ,t1 as(select sex as 性别
4 ,sum(case when region='1' and age='1' then cnt end)as c北京1岁
5 ,sum(case when region='1' and age='2' then cnt end)as c北京2岁
6 ,sum(case when region='2' and age='1' then cnt end)as c天津1岁
7 ,sum(case when region='2' and age='2' then cnt end)as c天津2岁
8 from t group by sex)
9 select * from t1;
C北京1岁 C北京2岁 C天津1岁 C天津2岁
- ---------- ---------- ---------- ----------
M 126 136 142 124
F 102 123 125 122
SQL> select fsqlgen('tren','age','sex','region','eav') from dual;
FSQLGEN('TREN','AGE','SEX','REGION','EAV')
-------------------------------------------------------------------------------------------------------------------------
with t
as (select age,sex,region,count(*)cnt from tren group by age,sex,region)
,t1 as(select age as 年龄
,sum(case when sex='M' and region='1' then cnt end)as c男北京
,sum(case when sex='F' and region='1' then cnt end)as c女北京
,sum(case when sex='M' and region='2' then cnt end)as c男天津
,sum(case when sex='F' and region='2' then cnt end)as c女天津
from t group by age)
select * from t1
SQL> with t
2 as (select age,sex,region,count(*)cnt from tren group by age,sex,region)
3 ,t1 as(select age as 年龄
4 ,sum(case when sex='M' and region='1' then cnt end)as c男北京
5 ,sum(case when sex='F' and region='1' then cnt end)as c女北京
6 ,sum(case when sex='M' and region='2' then cnt end)as c男天津
7 ,sum(case when sex='F' and region='2' then cnt end)as c女天津
8 from t group by age)
9 select * from t1;
年 C男北京 C女北京 C男天津 C女天津
-- ---------- ---------- ---------- ----------
1 126 102 142 125
2 136 123 124 122
SQL>
|
[ 本帖最后由 〇〇 于 2010-8-6 15:40 编辑 ] |
|