日期:2014-05-16  浏览次数:20662 次

在oracle里使用UTL_RAW做汇总【转载】

我有一个表用来反映在不同时段下几个商店对某个物品的销售情况,?
period_key?? item_key store_key

19980104???? 1????? 1
19980104???? 1????? 2
19980104???? 2????? 1
19980104???? 2????? 3
19990104???? 2????? 1
19990104???? 2????? 3

我主要想知道几个时段内物品在几家店有售。一般都用下面的sql来做
select count(distinct store_key)? from *
where period_key between ? and ?
and item_key =?


但数据太多, 统计时间太长, 所以想建一个汇总表来减少数据量. 象这样

period_key??? item_key? distinct_store_key
19990104???? 1??????? 1,2,5,7,9
20010104???? 2??????? 2,5,6,8
..

但用distinct_store_key来找distinct count, 是字符操做, 也太慢, 我想把distinct_store_key变成其它格式, 下面用bit和位置来代表distinct_store_key

这样
{1,2,5,7,9} --> 101010011
{2,5,6,8} --> 010110010

然后进行或操作。

基本上,你的primary key有多少种取值可能,你用来代表这个table的数在二进制下就有多少位

UTL_RAW里有个函数BIT_OR很有用,我先把不同时段的store key放到一table的string字段里, 然后每次统计时用UTL_RAW.BIT_OR来得出几个时段中store key的并集, 再计算出并集中的count.

procedure test_raw_or IS
lvc_cursor ref_cursor;
lvn_counter BINARY_INTEGER;
lvs_a varchar2(4000);
RAW_a RAW(4000);
RAW_b RAW(4000);
RAW_c RAW(4000);
begin

OPEN lvc_cursor FOR
select bitmap_data from yh_bitmap;

lvn_counter := 0;
lvs_a := '';
LOOP
EXIT WHEN lvc_cursor%NOTFOUND;
lvn_counter := lvn_counter + 1;

FETCH lvc_cursor
INTO lvs_a;
RAW_a := UTL_RAW.CAST_TO_RAW(lvs_a);
if lvn_counter > 1 then
RAW_c := UTL_RAW.BIT_OR(RAW_a, RAW_b);
RAW_b := RAW_c;
else
RAW_b := RAW_a;
end if;

END LOOP;
CLOSE lvc_cursor;

insert into yh_calc_bitmap values (UTL_RAW.CAST_TO_varchar2(RAW_c));
commit;

end;

UTL_RAW.BIT_OR执行速度很快