2011/02/04

連続する値の表示を抑制する方法 (Suppress duplicated values)

一覧の印刷において、列の値が連続する場合には表示を抑制したい、という要件があります。
以下の例の「Dept#」列の様な出力イメージです。






BI Publisherを使用する場合、この要件に対しては、2つの実装方法が考えられます。
  1. SQLで実装(データソースがSQLの場合のみ)
  2. テンプレートで実装
それぞれの実装方法を順に説明します。



【1. SQLで実装】
上図の様な出力をSQLで実装するには、SQLの集計関数LAGとDECODEを組み合わせて使用します。
具体的なSQLは以下の通りです。

select deptno,
       decode(lag(deptno)over(order by deptno), deptno, null, deptno) as deptno_disp,
       empno,
       ename,
       job,
       mgr,
       to_char(hiredate, 'yyyy-mm-dd') as hiredate,
       sal,
       comm
  from scott.emp
 order by
       deptno,
       empno
BI Publisher側では、レコードを順に出力するだけで事足ります。
なお、ソート列とLAGの対象とする列が異なる場合にはPARTITION句の設定などが必要になります。参考まで、集計関数LAGの使用方法についてはマニュアルまたは以下のURLを参照してください。
http://oracle.se-free.com/dml/0601_lag.html



【2. テンプレートで実装】
SQLではなく、テンプレート側で対応するには、XSL関数preceding-siblingを使用します。以下のURLが参考になります。
http://winrichman.blogspot.com/2008/10/previous-next-element.html

しかしながら、単純に以下の様に指定しただけでは先頭行のDEPTNO(今回の例では”10”)が表示されません。
<?if:preceding-sibling::ROW[1]/DEPTNO!=DEPTNO?><?DEPTNO?><?end if?>



そこで、OR条件で1行目の判定を加えます。これにより、先頭行には常に値が出力されます。
<?if:preceding-sibling::ROW[1]/DEPTNO!=DEPTNO or position()=1?><?DEPTNO?><?end if?>

SQL側には何も変更を加える必要はありません。



【まとめ】
上述の通り、SQLおよびテンプレートのどちらでも、容易に実装が可能です。
個人的には、「”データの抽出”と”出力書式”を分離するべき」という観点から、データソースがSQLの場合でも、テンプレートでの対応が望ましいと考えます。SQLで対応した場合、そのデータソースは異なるテンプレートには使用できなくなる可能性があるためです。



[ Summary ]
On the first figure, the "Dept #" value appears only on the first record of each group.  You have two ways to achieve this with BIP.
1. SQL (when datasource is SQL)
  Use LAG and DECODE function.  See the SQL above (underlined part).

2. RTF template
  Use "preceding-sibling" and "position" as below:
<?if:preceding-sibling::ROW[1]/DEPTNO!=DEPTNO or position()=1?><?DEPTNO?><?end if?>

You can get more info of "preceding-sibling"
http://winrichman.blogspot.com/2008/10/previous-next-element.html

0 件のコメント:

コメントを投稿