1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Apexバッチで集計関数が使えない

Last updated at Posted at 2021-07-04

さくっと質問の回答をつくろうとしたら、エラーです。

Aggregate query does not support queryMore(), use LIMIT to restrict the results to a single batch

何で?えええええ。
調べたら解決策がありました。

#質問
https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000BdRF6SAN

#見直したプログラム
やっぱり、普通にアカウントから攻めた。

public class BAT_TowContactsOneAccount2 implements Database.Batchable<sObject> , Database.Stateful {
    
    private Integer executeCount = 0;  
    private Integer Count = 0;
    
    public BAT_TowContactsOneAccount2 () {
    }
    
    public Database.QueryLocator start(Database.BatchableContext BC) {
      
        return Database.getQueryLocator(getTargetQuery());
    }
    
    public void execute(Database.BatchableContext BC, List<Account> scope) {
        
        Savepoint sp = Database.setSavepoint();
        try {
            Count += scope.Size();
            executeCount++;
            
            List<Contact> insertContactList = new List<Contact>();
            system.debug(Logginglevel.INFO,'====scope===========>>> '+ scope );  
            for (Account Acc : scope) {
                system.debug(Logginglevel.INFO,'====Acc.Contacts.size()===========>>> '+ Acc.Contacts.size() );  
                If (Acc.Contacts.size() == 0) {
                    Contact c1 = new Contact();
                    c1.LastName = 'test2-1';
                    c1.FirstName = 'xx';
                    c1.AccountId = Acc.Id;
                    insertContactList.add(c1);
                    
                    Contact c2 = new Contact();
                    c2.LastName = 'test2-2';
                    c2.FirstName = 'xx';
                    c2.AccountId = Acc.Id;
                    insertContactList.add(c2);
                }
                
                If (Acc.Contacts.size() == 1) {
                    Contact c1 = new Contact();
                    c1.LastName = 'test2-1';
                    c1.FirstName = 'xx';
                    c1.AccountId = Acc.Id;
                    insertContactList.add(c1);
                    
                }
                
                
            }
            if (insertContactList.size() >0) insert insertContactList;        
            
        }catch(Exception e) {
            Database.rollback(sp);           
        } finally {
        }
    }
    
    public void finish(Database.BatchableContext BC) {
        System.debug('******** BAT_TowContactsOneAccount finish executeCount=' + executeCount + ', Count=' + Count);
        
    }
    
    private String getTargetQuery() {    	
        String query = 'SELECT Id,(SELECT Id FROM Contacts) FROM Account ';
        //system.debug(Logginglevel.INFO,'================>>>query '+ query );     
        return query;
    }

}

#最初のプログラム
考え方:コンタクトの数を数えて、2より小さいもを対象にすればいいかな?
撃沈!!!

よく考えたらコンタクトが無いアカウントが抽出できん。あたりまえだな。

public class BAT_TowContactsOneAccount implements Database.Batchable<AggregateResult> , Database.Stateful {

    private Integer executeCount = 0;  
    private Integer Count = 0;
    
    public BAT_TowContactsOneAccount () {
    }
    
    public Iterable<AggregateResult> start(Database.BatchableContext BC){
        System.debug('******** BAT_TowContactsOneAccount start');
        String query = 'SELECT Count(Id),AccountId FROM Contact Group by AccountId HAVING COUNT(Id) < 2';
        return new SearchResultIterable(query);
    } 
    
    //public Database.QueryLocator start(Database.BatchableContext BC) {
    //   
    //    return Database.getQueryLocator(getTargetQuery());
    //}    
    
    
    public void execute(Database.BatchableContext BC, List<AggregateResult> scope) {
        
        Savepoint sp = Database.setSavepoint();
        try {
            Count += scope.Size();
            executeCount++;
            
            List<Contact> insertContactList = new List<Contact>();
            system.debug(Logginglevel.INFO,'====scope===========>>> '+ scope );  
            for (AggregateResult AR : scope) {
                If (AR.get('expr0') ==0) {
                    Contact c1 = new Contact();
                    c1.LastName = 'test2-1';
                    c1.FirstName = 'xx';
                    c1.AccountId = (Id)AR.get('AccountId');
                    insertContactList.add(c1);
                    
                    Contact c2 = new Contact();
                    c2.LastName = 'test2-2';
                    c2.FirstName = 'xx';
                    c2.AccountId = (Id)AR.get('AccountId');
                    insertContactList.add(c2);
                }
                
                If (AR.get('expr0') ==1) {
                    Contact c1 = new Contact();
                    c1.LastName = 'test1';
                    c1.FirstName = 'xx';
                    c1.AccountId = (Id)AR.get('AccountId');
                    insertContactList.add(c1);
                }
            }
            if (insertContactList.size() >0) insert insertContactList;        
            
        }catch(Exception e) {
            Database.rollback(sp);           
        } finally {
        }
    }
    
    public void finish(Database.BatchableContext BC) {
        System.debug('******** BAT_TowContactsOneAccount finish executeCount=' + executeCount + ', Count=' + Count);
        
        
    }
    
    //private String getTargetQuery() {    	
    //    String query = 'SELECT Count(Id),AccountId FROM Contact Group by AccountId HAVING COUNT(Id) < 2 ';
    //    //system.debug(Logginglevel.INFO,'================>>>query '+ query );     
    //    return query;
    //}
    
    public class SearchResultIterator Implements Iterator<AggregateResult>{
        public AggregateResult [] results {get;set;}
        public Integer index {get;set;}
        
        public SearchResultIterator(String query){
            this.index = 0;
            results = Database.query(query);
        }
        
        public boolean hasNext(){
            return results !=null && !results.isEmpty() && index < results.size();
        }
        
        public AggregateResult next(){
            return results[index++];
        }
    }
    
    public class SearchResultIterable implements Iterable<AggregateResult>{
        private String query;
        
        public SearchResultIterable(String soql){
            this.query = soql;
        }
        
        public Iterator<AggregateResult> Iterator(){
            return new SearchResultIterator(this.query);
        }
    }
}
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?