3

I need to create a summaries record for each result generated by the following query, which returns around 12K.

The trouble is the aggregate result has to query 600K records, so I get 'System.LimitException: Too many query rows: 50001'.

What should be the right strategy here? Generate a list of contract and call out smaller queries for ~12K of them?

Your advice will be appreciated.

List<AggregateResult> queryCurrentYear = [select TI_Contract__c cntr, Line__c line, count(id) recscount, sum(number_of_calls__c) totalcalls, sum(total_costs__c) totalcost, max(ti_contract__r.value__c) value from detailed_call_data__c where (date__c >= :dateStart) and (date__c <= :dateEnd) and ti_contract__c !='' GROUP BY TI_Contract__c, Line__c]; 

1 Answer 1

4

On the face of it, a Batch on Contract would be appropriate. I would write the batch to iterate the Contracts and have the execute perform the aggregate query and related processing. Your aggregate query would simply change to:

public Database.QueryLocator start(BatchableContext context) {
    // You might like to restrict the contracts examined, e.g. to those
    // active in the current year or whatever. That's logic you can decide on
    return [SELECT Id FROM TI_Contract__c]; 
}

public void execute(BatchableContext context, List<TI_Contract__c> contracts) {
    // Note that dateStart and dateEnd are attributes of the batch
    List<AggregateResult> queryCurrentYearForContracts = [
        SELECT TI_Contract__c cntr, Line__c line, COUNT(Id) recscount,
               SUM(number_of_calls__c) totalcalls, SUM(total_costs__c) totalcost,
               MAX(ti_contract__r.value__c) value
        FROM detailed_call_data__c
        WHERE (date__c >= :dateStart) AND (date__c <= :dateEnd) AND
              ti_contract__c IN :contracts GROUP BY TI_Contract__c, Line__c
    ];

    ...
}

You can then make it such that you adjust the batch execution's scope size to best fit with the data you have - e.g. by making it a custom metadata instance value or a custom setting field. That way the admin can adjust the size if governor limits get exceeded during batch execution.

3
  • Phil, many thanks for your recommendation; I hope i did the right interpretation. I am now facing the problem when trying to deploy, I get an error: System.UnexpectedException: No more than one executeBatch can be called from within a test method. Please make sure the iterable returned from your start method matches the batch size, resulting in one executeBatch invocation. Stack Trace: External entry point. I have stripped everything out but can't figure it out. Any thoughts? Many thanks in advance.
    – wmin
    Nov 11, 2019 at 23:13
  • 1
    Hi @wmin I recommend you create a new question to cover that. However, in the meantime take a look at the trailhead for testing batches. It sounds a bit like you might have marked it as SeeAllData, which would be a bad idea - tests should set up the data they need for testing rather than rely on data already in the database.
    – Phil W
    Nov 12, 2019 at 7:08
  • Many thanks, Phil!
    – wmin
    Nov 12, 2019 at 15:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .