今回は、大量レコードからある特定の値が重複しているレコードを抽出する実装方法を紹介します。
Salesforce標準機能である重複ルールを使用することで、レコード画面上で重複を見つけることは可能ですが、今回はApex処理内で重複レコードに対し、なにかしらの処理を行いたいというケースを想定するとします。
◆今回は以下の条件下での重複レコードを探すとします。
-外部システムからユーザのログ情報がSalesforce上のオブジェクトに日次で連携される。
-ログ情報を日次で取引先責任者のデータに反映する。
-「ユーザ管理番号」をログ情報と取引先責任者でキーとして持っている。
-ログ情報は、累積データのため日次で連携されるレコードに「ユーザ管理番号」は重複しない。
→そのため「ユーザ管理番号」が重複する場合は、取引先責任者への反映を行わず、エラーレコードとして別途管理する。
◆オブジェクト定義
-ログ管理オブジェクト(Logs__c)
・「ユーザ管理番号」(user_number__c)
大まかな流れとして、以下のロジックで実装ができます。
①SOQLを使って、「ユーザ管理番号」をグーピングし2件以上存在する「ユーザ管理番号」を取得する
②取得した「ユーザ管理番号」を検索条件とし、ログ管理オブジェクトからレコードを取得。
実際の実装がこちらです。
List<AggregateResult> results = [SELECT user_number__c FROM Logs__c GROUP BY user_number__c HAVING Count(Id) >= 2];
Set<String> dupUserNumber = New Set<String>();
for(AggregateResult r: results){
dupUserNumber.add(String.ValueOf(r.get('user_number__c')));
}
List<Logs__c> dupRecordList = [SELECT id, user_number__c FROM Logs__c WHERE user_number__c IN :dupUserNumber];
AggregateResultは、SOQLに Count() などの集計関数が含まれる場合に、このsObjectに返す必要があります。AggregateResultからSELECTで取得した項目ごとの値を取得する場合は、.get(‘項目名’)で値を取得することが可能です。今回の実装で言うと、get(‘user_number__c’)に当たります。ここで取得した値はObject型になっているため、String型に変換をしSetに格納しています。
Apex内で集計関数を使用したSOQLを書いた場合、通常のSOQLのようにオブジェクトのリスト(今回で言うとLogs__c)では結果を受け取れず、「AggregateResult」を使用する必要があるため注意が必要です。また、AggregateResultリストの値の取得方法も、通常のオブジェクトは異なります。
今回紹介した重複レコードの抽出処理や、Apex内で集計関数を使用したSOQLを書く際はぜひ参考にしてみてください!
参考ページ:
-AggregateResult | SOAP API 開発者ガイド
https://developer.salesforce.com/docs/atlas.ja-jp.api.meta/api/sforce_api_calls_query_aggregateresult.htm
-SOQL 集計関数の使用
https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/langCon_apex_SOQL_agg_fns.htm