日志報表查詢
最近在做一個流水表的報表查詢,做下小結。
一般情況下對于數據量比較大的流水日志,都是按月隔接存儲的,所以在生成跨月甚至是跨年報表的時候,需要做特殊的處理。以下記錄我的處理方式,供參考。
思路:
1、 生成臨時表:查詢出的數據都放在該臨時表。
2、 按月查詢:將查詢條件中的開始時間到結束時間之間的數據按月依次查詢。
3、 查詢:(Oracle數據庫)
參數定義:Start_Date 開始時間
End_Date 結束時間
Tmp_Date 當前時間
Tmp_Data 臨時數據表
Month_TBName 月表名
Tmp_Date = Start_Date
While Tmp_Date < End_Date
Month_TBName = tuunc(Tmp_Date,’month’)
Tmp_Date = Add_Months(Tmp_Data,1) 注:下次查詢為下月表數據
If Tmp_Date > End_Date
查詢Month_TBName月表中日期Between Start_Date And End_Date的數據,放入Tmp_Data表
Else
查詢Month_TBName全月表數據,放入Tmp_Data表
3、 存儲過程
--SP統計
procedure xp_SPStat(areacode varchar2,
songId varchar2,
dateStart varchar2,
dateEnd varchar2,
spID varchar2,
page number, --之前顯示的頁碼
pageSize number, --頁大小
pageAction varchar2, --翻頁命令:first、last、next、pre
total out number, --記錄總數
currentPage out number, --當前頁碼
totalPage out number, --總頁數
ret out number, --操作結果
rec_rc out ret_record --結果集
) is
tablename varchar2(100);
sqlstr varchar2(256) := '';
num_start number; --個數下限
num_end number; --個數上限
sqlstry varchar2(256) := '';
begin
if isStatOverSpaned(dateStart, dateEnd) then
--時間范圍過大
ret := ret_err_overspan;
return;
end if;
if statTempTable(areacode,songId,spID,dateStart, dateEnd, tablename) = false then
ret := ret_err_tmptable;
return;
end if;
--獲取總數
select count(*)
into total
from (select t.song_id, count(*) as statCount
from tsongdeallogtemp t
group by t.song_id);
--翻頁處理
pageTurn(page, pageSize, total, pageAction, currentPage, totalPage);
num_start := (currentPage - 1) * pagesize + 1;
num_end := currentPage * pagesize;
open rec_rc for
select *
from (select c. *, rownum rn
from (select a.statcount,
(select count(a.statcount) from (select count(*) as statcount
from tsongdeallogtemp t)
) FSTATCOUNT, b. *
from (select t.song_id, count(*) as statcount
from tsongdeallogtemp t
group by t.song_id) a,
tSong b
where a.song_id = b.song_id
order by a.statcount desc) c)
where rn between num_start and num_end;
ret := ret_ok;
when others then
sqlstry :=sqlerrm;
ret := ret_Failed;
end;
--sp統計臨時表操作
function statTempTable(vareacode varchar2,
vsongId varchar2,
vspID varchar2,
vdateStart varchar2,
vdateEnd varchar2,
pTabName out varchar2) return boolean is
ret boolean := false;
tmp_date date := to_date(vdateStart, 'YYYY-MM-DD');
v_dateS date := to_date(vdateStart, 'YYYY-MM-DD');
v_dateE date := to_date(vdateEnd, 'YYYY-MM-DD');
tmpCount number := 0;
iCount number := 0;
tablename varchar2(100);
sqlstr varchar2(516);
tempSql varchar2(100);
begin
--獲取臨時表名
tablename := getSongDealTabName(1);
pTabName := tablename;
sqlstr := 'delete from ' || tablename;
execute immediate sqlstr;
--往臨時表中寫入數據
while tmp_date <= to_date(vdateEnd ||'23:59:59', 'YYYY-MM-DD HH24:MI:SS') loop
tablename := 'TSONGDEALLOG' ||
to_char(trunc(tmp_date, 'month'), 'YYYYMM');
select count(*)
into iCount
from tab t
where t.tname = tablename;
if iCount <= 0 then
return ret;
end if;
tmp_date := add_months(tmp_date, 1);
tmpCount := tmpCount + 1;
if vsongId is not null then
tempSql:=' t.song_id='''||vsongId||''' ';
else
tempSql:=' t.song_id like '''||vspID||'%'' ';
end if;
if tmp_date >= to_date(vdateEnd||'23:59:59', 'YYYY-MM-DD HH24:MI:SS') then
tablename || ' t where '|| tempSql ||
' and t.PHONE_CODE like '''||vareacode||'%'''||
' and t.add_time between '||
'to_date('''||vdateStart|| ' 00:00:00'',''yyyy-mm-dd HH24:MI:SS'') and ' ||
'to_date('''||vdateEnd|| ' 23:59:59'',''yyyy-mm-dd HH24:MI:SS''))';
execute immediate sqlstr ;
else
sqlstr := 'insert into tsongdeallogtemp select * from ' ||
tablename || ' t where '|| tempSql ||
' and t.PHONE_CODE like '''||vareacode||'%''';
execute immediate sqlstr ;
end if;
commit;
return true;
exception
when others then
sqlstr:=sqlerrm;
return false;
rollback;
end;