考え方としてはプロシージャにおけるグルーピング集計処理と同じになりますが、データプロバイダー言語としての表現がありますので、その点を押さえてください。
まず前提となるデータモデルのおさらいです。前提としては集計の起点となるベーステーブルと集計の対象となるテーブルが1対nのリレーショナルモデルとなります。
データモデルの例。 Customerテーブルを1に対してInvoiceテーブルがnのリレーショナルモデル |
データプロバイダーのOUTPUTとなるSDTを作成します。
グルーピング項目と集計項目のみのSDT |
1.ローカル式を使ったグルーピング集計
グルーピング集計用データプロバイダーです。ここではローカル式(SUM)を使用しています。SDT_CustomerInvoice
{
CustomerID = CustomerId
CustomerName = CustomerName
InvoiceAmount = SUM(InvoiceAmount)
}
今回の例ではCustomerテーブルとInvoiceテーブルの間はCustomerIdによって1対nのリレーションが存在するので、SQLでいう所の「Customer.CustomerID = Invoice.CustomerId」という条件が自動的に組み込まれます。
Webパネルは今までと同じ作り方です。
Refreshイベントでデータプロバイダーを呼び出してSDTコレクションを取得 |
SDTコレクションをGridとしてWebFormに貼り付ける |
ナビゲーションを見てみましょう。ローカル式 SUMによる集計式が展開されています。この場合、生成されるSQL文は一つになりますので処理効率的にも有利です。
2.入れ子のFor eachを使ったグルーピング集計
ローカル式と同じ結果を得る別な実装方法としては入れ子のFor eachを使います。データプロバイダーでは直接For eachコマンドは記述できません。{ } で括られたレベルを入れ子に記述します。
SDT_CustomerInvoice
{
CustomerID = CustomerId
CustomerName = CustomerName
&InvoiceAmount = 0
DUMMY
{
&InvoiceAmount = &InvoiceAmount + InvoiceAmount
}
InvoiceAmount = &InvoiceAmount
}
但し、今回のOUTPUTは1レベル構造のSDTですので、内側のレベルは出力する必要がありません。こういったケースでは[NOOUTPUT]オプションを付加することにより、そのレベルがOUTPUT対象からは除外されます。
試しに[NOOUTPUT]オプションを記述せずにビルドすると、OUTPUT構造と一致しないというビルドエラーになります。
ナビゲーションを見てみましょう。
ナビゲーションも入れ子のFor eachと認識しています。この場合はそれぞれSQLが生成され二重のカーソル処理になります。
処理効率という点ではローカル式には劣りますが、ローカル式で指定できない条件を使いたい場合はにはこの入れ子のFor eachを使います。
例えば、Whenを含んだ条件などです。※
Where InvoiceDate >= &StartDate When not &StartDate.IsEmpty()
3.コントロールブレイクによるグルーピング集計
コントロールブレイクを使ったグルーピング集計の場合、前述したローカル式や入れ子のFor eachとは出力される結果が違ってきます。SDT_CustomerInvoice
Defined by InvoiceDate
{
CustomerID = CustomerId
CustomerName = CustomerName
&InvoiceAmount = 0
DUMMY [NOOUTPUT]
{
&InvoiceAmount = &InvoiceAmount + InvoiceAmount
}
InvoiceAmount = &InvoiceAmount
}
今回のケースでは、前述の入れ子のFor eachソースに対し外側のFor eachにDefined byオプションを追加しているだけです。これはデータプロバイダーに限らず、For eachコマンドを使ってコントロールブレイクを実装する場合と共通です。(全てのFor eachでベーステーブルを揃える)
ナビゲーションを見てみましょう。
2つのFor eachが同じベーステーブルになつているので、内側のFor eachがBreakとして解釈されています。
実行結果です。違いがわかりますか?
コントロールブレイクを使った場合、他の2つとの違いはInvoiceが0件のCustomerは抽出対象になっていません。つまり「売上データを持った顧客のみを抽出」している事になります。
一方、SUMや入れ子のFor eachを使った場合は、外側=Customer、内側=Invoiceとベーステーブルが違いますので「全顧客に対して売上データを集計して抽出」という事になります。
0 件のコメント:
コメントを投稿