以下の様なデータモデルで、Invoice一覧の画面を実装する時に、検索条件としてInvoiceDetailつまり明細の項目を含めたい場合はどう実装したらよいでしょうか?
例えばfor eachコマンドで記述してみます。
for each
//ヘッダーの項目属性
where InvoiceDate = &InvoiceDate when not &InvoiceDate.IsEmpty()
where CustomerName like &CustomerName when not &CustomerName.IsEmpty()
//明細の項目属性
where ProductDescription like &ProductDescription when not &ProductDescription.IsEmpty()
//表示項目は全てヘッダーの項目属性
&InvoiceId = InvoiceId
&InvoiceDate = InvoiceDate
&CustomerName = CustomerName
&InvoiceAmount = InvoiceAmount
Load
when none
// not found時の処理
endfor
いかがでしょうか? 皆さんの考えた通りの記述でしたか?
実はこの記述は間違いです。想定する動作になりません。
このfor eachコマンドをGeneXusが解析すると「ベーステーブル=InvoiceDetail、拡張テーブル=InvoiceDetail、Invoice、Customer」となります。
InvoiceDetailがベーステーブルになるので明細が複数あるInvoiceレコードに関しては同じデータが明細数分一覧表示される事になります。拡張テーブルはSQLではINNER JOINになります。
実際の挙動。明細の件数分同じヘッダーデータが抽出されます。又、明細が無いヘッダーは抽出されません。
GeneXusがベーステーブルを特定する時のポイントは「for eachコマンド内に記述された項目属性」つまりOrder節やWhere節に記述された項目属性も含みます。
今回の例では、Where節にProductDescriptionを加えてしまった時点で、Invoiceがベーステーブルになる事はありません。
では、今回の様な要件を実装したい場合はどうしたらよいでしょうか?
一般的(SQLでは)にはサブクエリ(副問い合わせ)を使用しますが、GeneXusではデータセレクタ※を使う事により実装が可能になります。
※データセレクタとは、Order/Where/Defined by といったfor eachコマンドに対するオプションを部品化し、複数の箇所(for eachコマンド/Grid/式など)で再利用する事を目的としたオブジェクトです。
まず、データモデルで説明すると、for eachのベーステーブル・拡張テーブルとサブクエリ側=データセレクタのベーステーブル・拡張テーブルが以下の様になります。
以下が実際の定義です。
・データセレクタの作成
Parameter | データセレクターのパラメータ定義 parmルールと同じ |
Order | for eachコマンドのOrder節定義 |
Condition | for eachコマンドのWhere節定義 |
Defined by | for eachコマンドのDefined by定義 |
・for eachコマンドの記述
for each
//ヘッダーの項目属性
where InvoiceDate = &InvoiceDate when not &InvoiceDate.IsEmpty()
where CustomerName like &CustomerName when not &CustomerName.IsEmpty()
//データセレクターを使った副問い合わせ
where InvoiceId in InvoiceDetailDataSelector( &ProductName ) when not &ProductName.IsEmpty()
//表示項目は全てヘッダーの項目属性
&InvoiceId = InvoiceId
&InvoiceDate = InvoiceDate
&CustomerName = CustomerName
&InvoiceAmount = InvoiceAmount
Load
when none
// not found時の処理
endfor
GeneXusの解析結果でベーステーブルがInvoice、拡張テーブルがInvoice、Customerになっています。
実際の挙動。複数明細持っているヘッダーデータも1件しか抽出されません。又、明細が無いヘッダーデータは抽出されるようになりました。
0 件のコメント:
コメントを投稿