参照関係で積み上げ集計を行う方法

By | January 3, 2022

まず言いたい

主従関係への変更に障害がなければ、主従関係に変更しましょう。

参照関係の項目のデータ型を主従関係に変更する場合の影響については、「参照関係を主従関係に変更する場合の考慮事項」を参照してください。

選択肢一覧

  • DLRS
  • フロー
  • Apexトリガ
  • レポート
  • BI(Tableau CRM/Tableau)
  • SF外での集計

選択肢

■DLRS

AppExchange。おすすめ。詳細は「DLRS(Declarative Lookup Rollup Summaries Tool)設定マニュアル」を参照。

■フロー

非推奨。フローでの実装は「潜在的に環境を破壊する行為」といっても過言ではありません。

「子レコードの作成/更新/削除時に親レコードに更新をかける」ような処理の場合、子レコードに対するバッチ処理時に容易に’maximum number of duplicate updates in one batch’エラーが発生します。非同期化すればある程度緩和されますが、制限は依然として厳しく、子レコードをまとめて作成/更新/削除する際に制限超過するリスク(別の言い方をすれば、子レコードに一括処理をかけらないという制約)に永久に支配されることとなります。

■Apexトリガ

DLRSでは対応できないような処理がある場合・既存のFrameworkに載せたい場合などはこれかなと思います。

サンプルコード↓

trigger BillingDetailTrigger on BillingDetail__c (after delete, after insert, after update) {

	Set<id> billingIds = new Set<id>();
	List<billing__c> billingsToUpdate = new List<billing__c>();

    if(Trigger.isInsert){
        for (BillingDetail__c billingdetail : Trigger.new){
                billingIds.add(billingdetail.BillingNo__c);
        }
    }

	if (Trigger.isUpdate) {
		for (BillingDetail__c billingdetail : Trigger.new){
            BillingDetail__c oldBd = Trigger.oldMap.get(billingdetail.Id);
            if(billingdetail.Amount__c != oldBd.Amount__c){
                billingIds.add(billingdetail.BillingNo__c);
            }          
        }			
	}

	if (Trigger.isDelete) {
		for (BillingDetail__c billingdetail : Trigger.old){
            if(billingdetail.Amount__c != null && billingdetail.Amount__c != 0){
            billingIds.add(billingdetail.BillingNo__c);
            }
        }			
	}

	// get a map of the billings with the number of billingdetails
	Map<id,Billing__c> billingMap = new Map<id,Billing__c>([select id, Num_BillingDetails__c,BasicCharge__c,Discount__c,InitialFee__c,OptionalCharge__c,RecordedAmount__c,Revenue__c,UsageCharge__c from Billing__c where id IN :billingIds]);

    
	// query the billings and the related inventory billingdetails and add the size of the inventory billingdetails to the billing's Num_BillingDetails__c
	for (Billing__c billing : [select Id, Name, Num_BillingDetails__c,(select id,BasicChargeAuto__c,DiscountAuto__c,InitialFeeAuto__c,OptionalChargeAuto__c,SalesAmountTaxSeparated__c,RevenueAuto__c,UsageChargeAuto__c from BillingNo__r) from Billing__c where Id IN :billingIds]) {
		Decimal Sum_BasicChargeAuto = 0;
        Decimal Sum_DiscountAuto = 0;
        Decimal Sum_InitialFeeAuto = 0;
        for(BillingDetail__C bd:billing.BillingNo__r){
            Sum_BasicChargeAuto += bd.BasicChargeAuto__c;
            Sum_DiscountAuto += bd.DiscountAuto__c;
            Sum_InitialFeeAuto += bd.InitialFeeAuto__c;
        }
        billingMap.get(billing.Id).Num_BillingDetails__c = billing.BillingNo__r.size();
        billingMap.get(billing.Id).BasicCharge__c = Sum_BasicChargeAuto;
        billingMap.get(billing.Id).Discount__c = Sum_DiscountAuto;
        billingMap.get(billing.Id).InitialFee__c = Sum_InitialFeeAuto;
		// add the value/billing in the map to a list so we can update it
		billingsToUpdate.add(billingMap.get(billing.Id));
	}

	update billingsToUpdate;


}

■レポート

レポートの集計関数で問題が解決するなら、それに越したことはありません。

■BI(Tableau CRM/Tableau)

同上

■SF外での集計

同上