マルチデータセットの階層帳票実現

  • 作成者:ayuan0625
  • 編集回数:27次
  • 最終更新:ayuan0625 于 2021-09-28
  • 一.説明

    帳票に使用されるデータの量が数百万行に達し、帳票の表示速度が遅いと感じる場合、階層帳票を使って表示速度を向上させることができます。しかし、階層帳票のマニュアルから分かるように、階層帳票は単一のデータセットである必要があります。そこで、本マニュアルではマルチデータセットのテンプレートで、且つデータ量が多い場合、帳票のクエリ速度を高める方法について紹介します。

    二.アイディア

    データセットを定義するとき、データベース自体の行番号を使用するか、またはデータベース関数を使用して行番号を生成し、且つwhere条件においてページ番号パラメータを使って行番号を特定の範囲内で表示させます。カスタマイズされた前ページ次ページボタンをクリックすると、ページ番号パラメータを再度読み込み、対応するデータを取得します。

    注:SQL Server2000は行番号を生成できないため、ストアドプロシージャの改ページクエリ実現を定義する必要があります。下にAccessの改ページ実現手順を詳しく紹介します。SQLServer2005とOracleデータベースの改ページ手順に少し違いがあるため、下に詳しく説明します。

    ユーザのアプリケーションシナリオがグリッドエンジンに対応しない場合、新しい計算エンジンプラグインを使用してください。当該プラグインはマルチデータソースにおける改ページクエリ機能を実現し、ユーザは複雑な改ページ SQLまたはJSボタンを再入力する必要がなく、帳票のトップページを速やかにロードすることができます。

    注:当該プラグインはOracle、SQL Server、MySQL、HANA、PostgreSQL、Impala、DB2など、ほとんどの主流のJDBCデータソースに対応します。

    三.Access改ページの例

    1.新規テンプレート

    新しいテンプレートmutipage.cptを作成します。

    表示速度を高めるため、改ページクエリを使用して各製品の詳細情報を取得し、製品に対応する注文における請求額を計算します。したがって、データセットds1を追加する時のクエリSQL文は次の通りです。

    select ProductID,Product_name, SupplierID , CategoryID, Unit_quantity, Unit_price, Inventory_quantity, Order_quantity from Product where ProductID between 10*(${page}-1)+1 and 10*${page} group by ProductID,Product_name, SupplierID , CategoryID, Unit_quantity, Unit_price, Inventory_quantity, Order_quantity order by ProductID

    パラメータpageのデフォルト値を1に設定します。最初に表示されるのは第一ページで、1番目から20番目のレコードのみがクエリされます。pageのパラメータが2の場合、21~40のレコードがクエリされ、つまり第二ページの内容になります。

    注:1ページに10項目のデータを表示するように帳票を定義します。つまり、ds1のクエリSQLは一度に10項目のデータのみを取り込むため、帳票の表示速度が速くなります。

    2.前ページ、次ページボタンのカスタマイズ

    改ページクエリを使用した後、帳票はpageパラメータに従って特定の範囲内における行番号のデータをクエリする必要があります。次のページをクリックすると、page1を足して帳票に転送し、次の10項目のレコードをクエリします。前のページをクリックすると、page1を減らして帳票に転送し、前の10項目のレコードをクエリします。帳票に組み込まれている前のページと次のページのボタンはこれらの操作を実行できないため、前のページと次のページのボタンをカスタマイズする必要があります。

    1.セルの中で前のページと次のページのページ番号の値を計算

    ツールバーからpageパラメータの値を直接取得することができないため、先ずセルの中で前のページと次のページのページ番号の値を計算し、次に、ツールバーボタンからセルの値を取得します。

    01.png

    2.前のページ、次のページボタンのカスタマイズ

    テンプレート>テンプレートWeb属性-改ページプレビュー設定をクリックし、テンプレート個別設定を選択して、ツールバーに2つのカスタムボタンを追加し、それぞれ前ページ次ページに命名して、ツールバーには次の図に示すようにいくつかのボタンだけを残します。

    02.png

    3.最初ページと最後ページの処理

    初めて帳票にアクセスするとき、デフォルトで最初のページpage = 1が表示されます。このとき、前のページのボタンは無効になっているはずです。そうでない場合、前ページのボタンをクリック(ページ番号は0)して、行番号が-9から0の間のレコードをクエリするとエラーが出ます。同様に、最後のページが表示されているとき、次ページのボタンが無効になっていなければなりません。つまり、前ページのページ番号page-1 = 0の場合、前ページが無効で、次ページのページ番号page > 総ページ数の場合、次のページが無効です。

    総ページ数の計算

    レコードの総数と各ページに表示されている項目数に応じて、総ページ数を計算します。データセットds2を追加し、SQL文は次の通り:SELECT count(*) as count FROM Product。製品表の総項目数をクエリして、次のようにセルにドラッグします。

    04.png

    総数のセルをダブルクリックしてデータ列設定ダイアログボックスをポップアップし、詳細-カスタマイズ表示を選択し、値に数式:roundup($$$ / 10,0)を入力して総ページ数を計算します。

    03.png

    一行目の行の高さを0に設定するか非表示に設定します。

    04.png

    前ページボタンの設定:前ページのカスタムボタンを選択し、カスタムイベントをクリックしてコールバック関数を設定し、JSに次の文を入力します。

    05.png

    var page = $( "tr[tridx=0]", "div.content-container").children().eq(0).html();
     //帳票が第一ページであると表示されている場合、前のページは使用できません
    if (page ==  0) {
    this.setEnable(false);
    } else {
    window.location.href = "${servletURL}?reportlet=doc/Advanced/multipage.cpt&page=" + page;
    }

    注:最初の文は前のページのページ番号(セルA1)の値を取得するという意味で、最後のhtml()はText()に置き換えることができます。2番目の文は帳票を再読み込みしてpageパラメータに値を割り当てるという意味です。

    注:ページ番号を取得するときにセルを結合した場合、取得するセルに注意しなければなりません。たとえば、セルD1の値を取得したい場合、セルを結合しなければ、eqの後の列の番号は3になります。列ABCのセルを結合した場合は、実際にはこれらを一つの全体として列の数をカウントするため、このとき、D1の値を取得するには、eqの後の列の数を1にする必要があります。

    前のページボタンの設定:次のページのボタン設定は前のページのJSとほぼ同じで、B1の値のみを取得すればいいため、JSに次の文を入力します。

    var page = $( "tr[tridx=0]", "div.content-container").children().eq(1).html();
    var total = $( "tr[tridx=0]", "div.content-container").children().eq(2).html(); 
    //帳票が最後のページであると表示されている場合、次のページは使用できません
    if ( parseInt(page) > parseInt(total) {
    this.setEnable(false);
    } else {
    window.location.href = "${servletURL}?reportlet=doc/Advanced/multipage.cpt&page=" + page;
    }

    注:初めて帳票を開くとき、pageパラメータはデータセットで定義されているため、帳票を初めて開くときにデータセットパラメータのデフォルト値をセルに転送することができないため、まったく同じテンプレートパラメータpageを定義して、デフォルト値を1に設定する必要があります。

    改ページプレビューすると、効果を確認することができます。

    四.SQL Server事例

    注:パラメータpageのデフォルト値を1に設定します。

    プラン1:ROW_NUMBER() OVER (ORDER BY主キーフィールド) AS rowno 行番号生成。

    データセットds1のクエリSQL文:

    select * from (SELECT *,ROW_NUMBER() OVER (ORDER BY ProductID) AS rowno FROM Product) as b where b.rowno between 20*(${page}-1)+1 and 20*${page}

    プラン2:NOT IN/TOPを使用する

    データセットds1のクエリSQL文:

    select top 20 * from Product where ProductID not in (select top (20*(${page}-1)) ProductID from Product order by Product) order by ProductID

    プラン3:NOT EXISTを使用する

    データセットds1のクエリSQL文:

    select top 20 * from Product where not exists (select 1 from (select top (20*(${page}-1)) ProductID from Product order by ProductID)a where a.ProductID=Product.ProductID) order by ProductID

    注:プラン1の改ページ方法を推薦します。ROW_NUMBER() はSQL2005及び以降のバージョンのみをサポートします。NOTEXISTSはNOTINより効率的です。

    五.Oracle事例

    Oracleデータベースには元々行番号ROWNUMがあるため、上記の例のds1データセットを次のように変更するだけで済みます。

    SELECT* FROM(select A.*,ROWNUM rn from(select * from Product)A where ROWNUM <= $ {page} + 20)where RN> = $ {page}。

    注:ROWNUMは、より小さいもののみに対応し、より大きなものをサポートしないため、上記のように定義する必要があります。

    六.MySQL事例

    注:パラメータpageのデフォルト値を1に設定します

    MySQLデータベースの改ページにはLIMIT文法が推奨されるため、上記の例のds1データセットを次のように変更するだけで済みます。

    プラン1:LIMIT

    データセットds1のクエリSQL文:

    SELECT * FROM Product ORDER BY ProductID LIMIT ${t},20

    さらに、次の図に示すように、パラメータtに数式を割り当てます:20 *($ page-1)。

    注:MySQLデータベースのSQL文は直接計算できないため、計算式は変数tに割り当てられます。

    06.png

    プラン2:limit+サブクエリ

    データセットds1のクエリSQL文:

    SELECT * FROM Product WHERE ProductID >=(SELECT ProductID FROM Product ORDER BY ProductID LIMIT ${t}, 1) LIMIT 20

    さらに、パラメータtに数式を割り当てます:20*($page-1)

    注:LIMITは 一つまたは二つの数値パラメータを受け入れ、パラメータは整数常数でなければなりません。2つのパラメータが指定されている場合、最初のパラメータは最初に返されるレコード行のオフセットを指定し、2番目のパラメータは返されるレコード行の最大数を指定します。最初のレコード行のオフセットは0です。

    Attachment List


    Theme: FineReport システム性能最適化
    • いいね
    • 良くない
    • 閲覧しただけ