Oracle中实现透视表 根据ERN的修改后的在Block_size 16K下我实现了56万行数据透视....

 
EXCEL的透视表是非常棒的一个功能,对于竖表转横表比较有用,我个人认为是除了那些公式计算以外EXCEL最吸引人的功能了。但是EXCEL有着65535行的限制,对于我们这些经常要为经营分析取数、做报表的人显然是远远不够的。Oracle中当然可以实现表的pivot,在 Expert One on One Oracle中讲分析函数的一章中也有一个例子讲解如何Pivot,但是Tom的pivot是类似于完全的转换,将几列全部打散(具体请到asktom.oracle.com搜索“pivot”或者参考上述书籍)。而我们需要的是一个Oracle的透视表。也就是如下的效果:

  1 None.gif CREATE   OR   REPLACE  PACKAGE pkg_pivot
  2 None.gif  AS
  3 ExpandedBlockStart.gifContractedBlock.gif   /**/ /******************************************************************************
  4InBlock.gif     NAME:       pkg_pivot
  5InBlock.gif     PURPOSE:
  6InBlock.gif  
  7InBlock.gif     REVISIONS:
  8InBlock.gif     Ver        Date        Author           Description
  9InBlock.gif     ---------  ----------  ---------------  ------------------------------------
 10InBlock.gif     1.0        2005-12-21  ERN           1. 创建包
 11InBlock.gif     2.0        2005-12-22  ERN           2. 增加pivot_long过程,处理超过200列
 12InBlock.gif                                                情况,但仍存在限制
 13ExpandedBlockEnd.gif  ******************************************************************************/

 14 None.gif  TYPE refcursor  IS  REF  CURSOR ;
 15 None.gif  TYPE ARRAY  IS   TABLE   OF   VARCHAR2 ( 30 index   by  binary_integer;
 16 None.gif   PROCEDURE  pivot(p_tablename  varchar2 ,
 17 None.gif                  p_anchor     varchar2 ,
 18 None.gif                  p_pivot      varchar2 ,
 19 None.gif                  p_value      varchar2 ,
 20 None.gif                  p_cursor    OUT refcursor);
 21 None.gif   PROCEDURE  pivot_long(p_tablename  varchar2 ,
 22 None.gif                       p_anchor     varchar2 ,
 23 None.gif                       p_pivot      varchar2 ,
 24 None.gif                       p_value      varchar2 );
 25 None.gif END ;
 26 None.gif /
 27 None.gif create   or   replace  package body pkg_pivot  as
 28 None.gif   procedure  pivot(p_tablename  varchar2 -- 表名,也可以输入查询
 29 None.gif                   p_anchor     varchar2 -- 不变的列名,对于多个列可以用逗号分隔
 30 None.gif                   p_pivot      varchar2 -- 将取值转换成列的列名
 31 None.gif                   p_value      varchar2 -- 填充的值字段
 32 None.gif                   p_cursor    out refcursor  -- 返回结果集
 33 None.gif                   )  as
 34 ExpandedBlockStart.gifContractedBlock.gif     /**/ /******************************************************************************
 35InBlock.gif       NAME:       pivot
 36InBlock.gif       PURPOSE:    竖表转横表,此过程返回结果集,仅处理组合后32767字节以下的语句。
 37InBlock.gif                   即大约可以处理200列的转换。
 38InBlock.gif    
 39InBlock.gif       REVISIONS:
 40InBlock.gif       Ver        Date        Author           Description
 41InBlock.gif       ---------  ----------  ---------------  ------------------------------------
 42InBlock.gif       1.0        2005-12-21   ERN          1. 创建
 43InBlock.gif    
 44ExpandedBlockEnd.gif    ******************************************************************************/

 45 None.gif    ar_col        array;  -- 存放转换后的列名
 46 None.gif     n_cnt          number ;
 47 None.gif    l_query        varchar2 ( 32766 );  -- 最终的执行语句
 48 None.gif     l_query_pivot  varchar2 ( 200 );  -- 统计p_pivot转换后的列数与取值
 49 None.gif    begin
 50 None.gif    n_cnt         : =   0 ;
 51 None.gif    l_query       : =   ' select  '   ||  p_anchor  ||   ' , ' ;
 52 None.gif    l_query_pivot : =   ' select distinct  '   ||  p_pivot  ||   '  from  '   ||
 53 None.gif                     p_tablename;
 54 None.gif     open  p_cursor  for  l_query_pivot;
 55 None.gif  
 56 None.gif    loop
 57 None.gif       exit   when  p_cursor % NOTFOUND;
 58 None.gif      n_cnt : =  n_cnt  +   1 ;
 59 None.gif       fetch  p_cursor
 60 None.gif         into  ar_col(n_cnt);
 61 None.gif     end  loop;
 62 None.gif    n_cnt : =  n_cnt  -   1 ;
 63 None.gif     close  p_cursor;
 64 None.gif  
 65 None.gif     for  i  in   1  .. n_cnt  -   1  loop
 66 None.gif      l_query : =  l_query  ||   ' max(val '   ||  to_char(i)  ||   ' ) " '   ||  ar_col(i)  ||   ' ", ' ;
 67 None.gif     end  loop;
 68 None.gif  
 69 None.gif    l_query : =  l_query  ||   ' max(val '   ||  to_char(n_cnt)  ||   ' ) " '   ||
 70 None.gif               ar_col(n_cnt)  ||   ' ' ;
 71 None.gif    l_query : =  l_query  ||   ' from (select  ' ;
 72 None.gif  
 73 None.gif    l_query : =  l_query  ||  p_anchor  ||   ' ' ;
 74 None.gif  
 75 None.gif     for  i  in   1  .. n_cnt  -   1  loop
 76 None.gif      l_query : =  l_query  ||   ' decode( '   ||  p_pivot  ||   ' , '   ||  ar_col(i)  ||
 77 None.gif                  ' ,rn, null) rn '   ||  to_char(i)  ||   ' , ' ;
 78 None.gif      l_query : =  l_query  ||   ' decode( '   ||  p_pivot  ||   ' , '   ||  ar_col(i)  ||   ' , '   ||
 79 None.gif                 p_value  ||   ' ,null) val '   ||  to_char(i)  ||   ' , ' ;
 80 None.gif    
 81 None.gif     end  loop;
 82 None.gif    l_query : =  l_query  ||   ' decode( '   ||  p_pivot  ||   ' , '   ||  ar_col(n_cnt)  ||
 83 None.gif                ' , rn, null) rn '   ||  to_char(n_cnt)  ||   ' , ' ;
 84 None.gif    l_query : =  l_query  ||   ' decode( '   ||  p_pivot  ||   ' , '   ||  ar_col(n_cnt)  ||   ' , '   ||
 85 None.gif               p_value  ||   ' ,null) val '   ||  to_char(n_cnt)  ||   '   ' ;
 86 None.gif  
 87 None.gif    l_query : =  l_query  ||   ' from (select  ' ;
 88 None.gif  
 89 None.gif    l_query : =  l_query  ||  p_anchor  ||   ' ' ;
 90 None.gif  
 91 None.gif    l_query : =  l_query  ||  p_pivot  ||   ' '   ||  p_value  ||
 92 None.gif                ' , row_number() over(partition by  ' ;
 93 None.gif  
 94 None.gif    l_query : =  l_query  ||  p_anchor  ||   ' ' ;
 95 None.gif  
 96 None.gif    l_query : =  l_query  ||  p_pivot  ||   '   ' ;
 97 None.gif    l_query : =  l_query  ||   ' order by  '   ||  p_value  ||   ' ) rn from  '   ||
 98 None.gif               p_tablename  ||   ' ) t) t group by  ' ;
 99 None.gif  
100 None.gif    l_query : =  l_query  ||  p_anchor  ||   '   ' ;
101 None.gif  
102 None.gif     execute  immediate  ' alter session set cursor_sharing=force ' ;
103 None.gif  
104 None.gif     open  p_cursor  for  l_query;
105 None.gif  
106 None.gif     execute  immediate  ' alter session set cursor_sharing=exact ' ;
107 None.gif  
108 None.gif   end ;
109 None.gif   procedure  pivot_long(p_tablename  varchar2 ,
110 None.gif                       p_anchor     varchar2 ,
111 None.gif                       p_pivot      varchar2 ,
112 None.gif                       p_value      varchar2 as
113 ExpandedBlockStart.gifContractedBlock.gif     /**/ /******************************************************************************
114InBlock.gif       NAME:       pivot_long
115InBlock.gif       PURPOSE:    竖表转横表,此过程建立_ext表,用于处理组合后查询语句超过32676
116InBlock.gif                   字节的情况;对超长语句必须用dbms_sql进行解析、执行。但此处还受
117InBlock.gif                   聚集过程中限制,对于过长的分组聚集语句会报ORA-01467,内部机制是
118InBlock.gif                   受块大小影响,除非使用16K的大块,否则无法绕过此问题。
119InBlock.gif    
120InBlock.gif       REVISIONS:
121InBlock.gif       Ver        Date        Author           Description
122InBlock.gif       ---------  ----------  ---------------  ------------------------------------
123InBlock.gif       1.0        2005-12-22   ERN          1. 创建
124InBlock.gif    
125ExpandedBlockEnd.gif    ******************************************************************************/

126 None.gif    ar_col        array;
127 None.gif    n_cnt          number ;
128 None.gif    l_tmp          varchar2 ( 3256 );
129 None.gif    p_cursor      refcursor;
130 None.gif    l_query       dbms_sql.varchar2s;
131 None.gif    n_ind          number ;
132 None.gif    n_left         number ;
133 None.gif    l_query_pivot  varchar2 ( 3200 );
134 None.gif    l_cursor       integer   default  dbms_sql.open_cursor;
135 None.gif    n_result       number ;
136 None.gif   begin
137 None.gif    --  l_query(1) :='1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890';
138 None.gif     n_cnt : =   0 ;
139 None.gif  
140 None.gif    l_query( 1 ) : =   ' create table  '   ||
141 None.gif                  substr(p_tablename,
142 None.gif                         instr(p_tablename,  ' . ' +   1 ,
143 None.gif                         instr(p_tablename,  ' where ' -
144 None.gif                         instr(p_tablename,  ' . ' -   2 ||   ' ext as  ' ;
145 None.gif  
146 None.gif    n_ind : =   2 ;
147 None.gif    l_query(n_ind) : =   ' select  '   ||  p_anchor  ||   ' , ' ;
148 None.gif    l_query_pivot : =   ' select distinct  '   ||  p_pivot  ||   '  from  '   ||
149 None.gif                     p_tablename;
150 None.gif     open  p_cursor  for  l_query_pivot;
151 None.gif  
152 None.gif    loop
153 None.gif       exit   when  p_cursor % NOTFOUND;
154 None.gif      n_cnt : =  n_cnt  +   1 ;
155 None.gif       fetch  p_cursor
156 None.gif         into  ar_col(n_cnt);
157 None.gif     end  loop;
158 None.gif    n_cnt : =  n_cnt  -   1 ;
159 None.gif     close  p_cursor;
160 None.gif  
161 None.gif
162 None.gif    n_ind : =  n_ind  +   1 ;
163 None.gif    l_query(n_ind) : =   '' ;
164 None.gif     for  i  in   1  .. n_cnt  -   1  loop
165 None.gif      l_tmp : =   ' max(val '   ||  to_char(i)  ||   ' ) " '   ||  ar_col(i)  ||   ' ", ' ;
166 None.gif --       if NVL(length(l_query(n_ind)), 0) + length(l_tmp) <= 255 then
167 None.gif        if  NVL(length(l_query(n_ind)),  0 +  length(l_tmp)  <=   100   then
168 None.gif --   gl      dbms_output.put_line(l_query(n_ind));
169 None.gif--   gl      dbms_output.put_line(lengthb(l_query(n_ind)));
170 None.gif         l_query(n_ind) : =  l_query(n_ind)  ||  l_tmp;
171 None.gif       else
172 None.gif        n_left : =   100   -  length(l_query(n_ind)); 
173 None.gif        l_query(n_ind) : =  l_query(n_ind)  ||  substr(l_tmp,  1 , n_left);
174 None.gif        n_ind : =  n_ind  +   1 ;
175 None.gif        l_query(n_ind) : =  substr(l_tmp, n_left  +   1 );
176 None.gif       end   if ;
177 None.gif     end  loop;
178 None.gif    n_ind : =  n_ind  +   1 ;
179 None.gif    l_query(n_ind) : =   '' ;
180 None.gif
181 None.gif    l_query(n_ind) : =   ' max(val '   ||  to_char(n_cnt)  ||   ' ) " '   ||  ar_col(n_cnt)  ||   ' ' ;
182 None.gif    l_query(n_ind) : =  l_query(n_ind)  ||   ' from (select  ' ;
183 None.gif  
184 None.gif    l_query(n_ind) : =  l_query(n_ind)  ||  p_anchor  ||   ' ' ;
185 None.gif    n_ind : =  n_ind  +   1 ;
186 None.gif    l_query(n_ind) : =   '' ;
187 None.gif     for  i  in   1  .. n_cnt  -   1  loop
188 None.gif      l_tmp : =   ' decode( '   ||  p_pivot  ||   ' , '''   ||  ar_col(i)  ||   ''' ,rn, null) rn '   ||
189 None.gif               to_char(i)  ||   ' , ' ;
190 None.gif      l_tmp : =  l_tmp  ||   ' decode( '   ||  p_pivot  ||   ' , '''   ||  ar_col(i)  ||   ''' , '   ||
191 None.gif               p_value  ||   ' ,null) val '   ||  to_char(i)  ||   ' , ' ;
192 None.gif       if  NVL(length(l_query(n_ind)),  0 +  length(l_tmp)  <=   100   then
193 None.gif        l_query(n_ind) : =  l_query(n_ind)  ||  l_tmp;
194 None.gif       else
195 None.gif        n_left : =   100   -  length(l_query(n_ind)); 
196 None.gif        l_query(n_ind) : =  l_query(n_ind)  ||  substr(l_tmp,  1 , n_left);
197 None.gif        n_ind : =  n_ind  +   1 ;
198 None.gif        l_query(n_ind) : =  substr(l_tmp, n_left  +   1 );
199 None.gif       end   if ;
200 None.gif
201 None.gif     end  loop;
202 None.gif    n_ind : =  n_ind  +   1 ;
203 None.gif    l_query(n_ind) : =   '' ;
204 None.gif    l_query(n_ind) : =   ' decode( '   ||  p_pivot  ||   ' , '''   ||  ar_col(n_cnt)  ||
205 None.gif                       ''' , rn, null) rn '   ||  to_char(n_cnt)  ||   ' , ' ;
206 None.gif    l_query(n_ind) : =  l_query(n_ind)  ||   ' decode( '   ||  p_pivot  ||   ' , '''   ||
207 None.gif                      ar_col(n_cnt)  ||   ''' , '   ||  p_value  ||   ' ,null) val '   ||
208 None.gif                      to_char(n_cnt)  ||   '   ' ;
209 None.gif    n_ind : =  n_ind  +   1 ;
210 None.gif    l_query(n_ind) : =   '' ;
211 None.gif    l_query(n_ind) : =   ' from (select  ' ;
212 None.gif  
213 None.gif    l_query(n_ind) : =  l_query(n_ind)  ||  p_anchor  ||   ' ' ;
214 None.gif  
215 None.gif    l_query(n_ind) : =  l_query(n_ind)  ||  p_pivot  ||   ' '   ||  p_value  ||
216 None.gif                       ' , row_number() over(partition by  ' ;
217 None.gif  
218 None.gif    l_query(n_ind) : =  l_query(n_ind)  ||  p_anchor  ||   ' ' ;
219 None.gif  
220 None.gif    l_query(n_ind) : =  l_query(n_ind)  ||  p_pivot  ||   '   ' ;
221 None.gif    n_ind : =  n_ind  +   1 ;
222 None.gif    l_query(n_ind) : =   '' ;
223 None.gif    l_query(n_ind) : =  l_query(n_ind)  ||   ' order by  '   ||  p_value  ||
224 None.gif                       ' ) rn from  '   ||  p_tablename  ||   ' ) t) t group by  ' ;
225 None.gif  
226 None.gif    l_query(n_ind) : =  l_query(n_ind)  ||  p_anchor  ||   '   ' ;
227 None.gif    
228 None.gif --     for i in 1..n_ind loop
229 None.gif--     dbms_output.put_line(l_query(i));
230 None.gif--     end loop;
231 None.gif   
232 None.gif    dbms_sql.parse(c              =>  l_cursor,
233 None.gif                   statement      =>  l_query,
234 None.gif                   lb             =>  l_query.first,
235 None.gif                   ub             =>  l_query.last,
236 None.gif                   lfflg          =>  false,
237 None.gif                   language_flag  =>   1 );
238 None.gif  
239 None.gif    n_result : =  dbms_sql. execute (c  =>  l_cursor);
240 None.gif    dbms_sql.close_cursor(c  =>  l_cursor);
241 None.gif   end ;
242 None.gif end  pkg_pivot;
243 None.gif /

此项的引用通告 URL 是:
http://yaoyp.spaces.live.com/blog/cns!ac5fd97b8a549660!534.trak
引用此项的日志

转载于:https://www.cnblogs.com/guola/archive/2007/02/07/643802.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值