|
我有一个表用来反映在不同时段下几个商店对某个物品的销售情况, 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执行速度很快 |