報表性能優化方案之多數據集實現層式報表

1. 問題描述
若報表使用的數據量是上百萬條的話,以爲報表展示的速度慢,可使用層式報表來提升報表展示速度。但由層式報表章節能夠得知,層式報表必須是單數據集,如果多數據集的模板且數據量又很大,想要提升報表的查詢速度要如何實現呢?html

2. 實現思路
在定義數據集時經過使用數據庫自己的行序號或者使用數據庫函數生成行序號(即行號)而且在where條件中經過頁碼參數使得行號在必定範圍內顯示,點擊自定義的上一頁下一頁按鈕時從新傳入頁碼參數取出相應的數據。web

注:SQL Server2000沒法生成行號,所以須要定義存儲過程實現分頁查詢,如下具體介紹Access實現分頁的步驟,SQL Server2005以及Oracle數據庫實現分頁的步驟有一點區別,如下會詳細介紹。數據庫

3. Access分頁示例
3.1 新建模板
新建模板mutipage.cpt,爲了加快展現速度,咱們可使用分頁查詢,獲取每一個產品的詳細信息並計算產品對應的訂單中的應付金額,所以添加數據集時查詢SQL語句爲select 產品.產品ID,產品名稱, 供應商ID , 類別ID, 單位數量, 產品.單價, 產品.庫存量, 產品.訂購量,sum(應付金額) as 應付款項 from 產品,訂單,訂單明細 where 產品.產品ID=訂單明細.產品ID and 訂單明細.訂單ID=訂單.訂單ID and 產品.產品ID between 10*(${page}-1)+1 and 10*${page} group by 產品.產品ID,產品名稱, 供應商ID , 類別ID, 單位數量, 產品.單價, 產品.庫存量, 產品.訂購量 order by 產品.產品ID,設置參數page的默認值爲1,首次看到的是第一頁,只查詢出第1~20條記錄;若page參數爲2時,查詢出第21~40條記錄,即第二頁內容。函數

注:這邊定義報表每頁顯示10條數據,即ds1的查詢SQL一次只取10條數據,從而加快報表展現速度。工具

3.2 自定義上一頁、下一頁按鈕
使用分頁查詢後,報表須要根據page參數查詢出行號在必定範圍內的數據,當點擊下一頁時,page須要加1並傳入報表查詢出後10條記錄;點擊上一頁時,page須要減1並傳入報表查詢出前10條記錄。而報表內置的上一頁下一頁按鈕沒法作這些操做,所以須要自定義上一頁下一頁按鈕。this

  • 在單元格中求出上一頁、下一頁頁碼的值orm

在工具欄中沒法直接獲取page參數的值,所以先在單元格中求出上一頁下一頁的頁碼值,而後再在工具欄按鈕中獲取單元格的值。htm

  • 自定義上一頁下一頁按鈕ip

點擊模板>模板web屬性>分頁預覽設置分,選擇爲該模板單獨設置,在工具欄中增長兩個自定義按鈕分別命名爲上一頁,下一頁,是工具欄上只剩下以下圖所示幾個按鈕。get

3.3 第一頁與最後一頁的處理
首次訪問報表時,默認顯示第一頁page=1,此時上一頁按鈕應該是無效的,不然點擊上一頁按鈕時(頁碼爲0),此時查詢行號在-9到0之間的記錄將會出錯;一樣,顯示到最後一頁時需下一頁按鈕無效。即當上一頁頁碼page-1=0時,上一頁無效;當下一頁頁碼page>總頁數時,下一頁無效。

  • 求出總頁數

根據總記錄數及每頁顯示條數,求出總頁數。新增數據集ds2,SQL語句爲:SELECT count(*) as 總數 FROM 產品,查詢出產品表總條數,拖入單元格,以下

雙擊總數所在單元格彈出數據列設置對話框,選擇高級>自定義顯示,在自定義中填入公式:roundup($$$/10,0)求出總頁數。

將第一行的行高設置爲0,或者是隱藏:

上一頁按鈕設置:選中上一頁自定義按鈕,點擊自定義JavaScript,在js中填入:

  1. var page= $("tr[tridx=0]","div.content-container").children().eq(0).html();    

  2. if(page==0)//若是報表顯示第一頁,則上一頁不可用  

  3. this.setEnable(false);  

  4. else  

  5. window.location.href="${servletURL}?reportlet=doc/Advanced/multipage.cpt&page="+page;   

注:第一句是獲取上一頁頁碼(A1單元格)的值,其中最後的html()能夠用Text()代替;第二句是從新加載報表並給page參數賦值。

上一頁按鈕設置:下一頁按鈕設置與上一頁的js差很少,只須要獲取B1的值就能夠了,因此在js中填入:

  1. var page= $("tr[tridx=0]","div.content-container").children().eq(1).html();    

  2. var total=$("tr[tridx=0]","div.content-container").children().eq(2).html();    

  3. if(parseInt(page) > parseInt(total))//若是報表顯示最後一頁,則下一頁不可用  

  4. {  

  5. this.setEnable(false);  

  6. }  

  7. else  

  8. window.location.href="${servletURL}?reportlet=doc/Advanced/multipage.cpt&page="+page;   

注:首次打開報表的時候,因爲page參數是在數據集中定義的,數據集參數的默認值在第一個次打開報表時沒辦法傳到單元格中,因此須要定義一個徹底同樣的模板參數page,默認值設爲1。這樣,首次打開模板時,上一頁按鈕一樣不可用。

分頁預覽,便可查看效果。mutipage.cpt

具體模板可參考:%FR_HOME%\WebReport\WEB-INF\reportlets\doc\Advanced\mutipage.cpt。

4. SQL Server2005示例
SQL Server2005使用ROW_NUMBER() OVER (ORDER BY 主鍵字段) AS rowno生成行號。

所以只須要修改數據集ds1查詢SQL語句爲select * from (SELECT *,ROW_NUMBER() OVER (ORDER BY year_school_id) AS rowno FROM year_school) as b where b.rowno between 20*(${page}-1)+1 and 20*${page}便可。

5. Oracle示例
Oracle數據庫中自己有行序號ROWNUM,所以只須要將上例ds1數據集修改爲以下:SELECT * FROM (select A.*,ROWNUM rn from (select * from year_school) A where ROWNUM <=${start}+20) where RN >=${start}便可。

注:ROWNUM只支持小於,大因而不支持的,所以要作如上定義。

相關文章
相關標籤/搜索