For eachの中にローカル式を記述する時、For eachのベーステーブルとローカル式のベーステーブル間にリレーションが無い場合は注意が必要です。
例) 国別に顧客数をカウント
1.リレーションがある場合
1-1.データモデル国マスタと顧客マスタで1対nのリレーションがあるモデルです。
![]() |
Country(国)トランザクションの定義 |
![]() |
Customer(顧客)トランザクションの定義 項目属性名の先頭にあるアイコンが上矢印になっています。 これは外部キー項目である事を表しています。 |
1-2.For eachコマンド + ローカル式
For each
&CountryName = CountryName
&CustomerCount = Count( CustomerName )
Endfor
For eachコマンドの中にローカル式(ここではCount)を記述しますが、GeneXusがリレーションを認識しているので条件は必要ありません。国1件に対して顧客がn件存在するので、その件数をカウントします。
![]() |
ビルド時に表示されるナビゲージョンレポート FormulasセクションでCustomerテーブルに対するCountに 「Given: CountryId」と条件が加わっています。 |
1-3.生成されるSQL
この場合以下の様なSQLが生成されます。
SELECT T1.[CountryId],GeneXusがリレーションを認識しているため、暗黙的にJOINが組み込まれます。
T1.[CountryName],
COALESCE( T2.[GXC1], 0) AS GXC1
FROM ([Country] T1 WITH (NOLOCK)
LEFT JOIN (
SELECT COUNT(*) AS GXC1, [CountryId]
FROM [Customer] WITH (NOLOCK)
GROUP BY [CountryId] ) T2
ON T2.[CountryId] = T1.[CountryId])
ORDER BY T1.[CountryId]
2.リレーションが無い場合
一方、リレーションが無いデータモデルの場合はどうなるでしょうか?2-1.データモデル
![]() |
Country(国)トランザクションは変わりませんが、Customer(顧客)トランザクション はCustomerCountryIdが指定されています。この場合、CountryトランザクションにあるCountryId とは項目属性名と一致しないので同一視しません。 項目属性名の先頭にあるアイコンが上矢印ではなく・になっています。(外部キーでは無い) |
![]() |
ダイアグラムに二つのテーブルを配置してみました。 CountryテーブルとCustomerテーブルの間にリレーションの線が表示されません。 これはGeneXusがリレーションを認識していないことを表しています。 |
2-2.For eachコマンド + ローカル式
この場合のローカル式はどう指定すればよいでしょうか? GeneXusはリレーションを認識していないので、Countローカル式に明示的な条件を指定する必要があります。
For each
&CountryName = CountryName
&CustomerCount = Count( CustomerName, CustomerCountryId = CountryId )
Endfor
![]() |
ビルド時に表示されるナビゲーションレポート FormulasセクションではCountの条件が「CustomerCountryId = CountryId」となっています。 注目すべきはCountのアクセス対象。CustomerテーブルとCountryテーブルの二つが挙げられています。 |
この場合以下の様なSQLが生成されます。
SELECT T1.[CountryId],
T1.[CountryName],
COALESCE( T2.[GXC1], 0) AS GXC1
FROM ([Country] T1 WITH (NOLOCK)
LEFT JOIN (
SELECT COUNT(*) AS GXC1,
T4.[CountryId]
FROM [Customer] T3 WITH (NOLOCK),
[Country] T4 WITH (NOLOCK)
WHERE T3.[CustomerCountryId] = T4.[CountryId]
GROUP BY T4.[CountryId] ) T2
ON T2.[CountryId] = T1.[CountryId])
ORDER BY T1.[CountryId]
オレンジ色の部分がFor eachに該当、青色の部分がCountローカル式に該当します。ローカル式で指定した条件がCount側にJOINとして追加されています。つまりこちらの方が一つ余分にJOINをしている事が判ります。
今回の例はシンプルなモデルですのでパフォーマンスの差は体感できませんが、実際のシステム開発で複雑なモデルや相当量のデータが前提になると目に見える差が発生する場合もあります。
この様に処理結果は同じでも、GeneXusが認識するリレーションの有無で生成されるコードが違う事がありますのでご注意下さい。
そしてローカル式の条件として変数を利用する場合は別な注意が必要です。これはまた次の機会に。
0 件のコメント:
コメントを投稿