1
List<Account> accList = [SELECT Id, Name FROM Account];
List<String> names = new List<String>();
for(Account a:accList) {
    names.add(a.Name);
}

Say I have 30,000 Account records and I want to get all the Account records Name field in a list, Is there a way of getting list of only account records Name field instead looping though the list of SOQL and adding Name field to another List.

1
  • I did do peformance analysis with this code: List<Account> accList = [SELECT Id, Name FROM Account LIMIT 10000]; List<String> names = new List<String>(); for(Account a:accList) { names.add(a.Name); } System.debug('Time: '+ Limits.getCPUTime()); Output : Time: 530 ________________________________________ Set<String> uniqueNames = new Map<String,SObject> ( [SELECT Name Id FROM Account Group By Name LIMIT 10000] ).keySet(); System.debug('Time: '+ Limits.getCPUTime()); Output: Time: 112 So using Aggregate is better than running a for loop in this scenario. Jan 7, 2023 at 4:31

2 Answers 2

1

To add to Derek's answer ...

You can do the following:

Set<String> uniqueNames = new Map<String,SObject> (
    [SELECT Name Id FROM Account Group By Name]
  ).keySet();

Grouping By Name works fine unless the name is an AutoNumber field which for Account, it is not. Aggregate queries will fail on extremely large record sets so using additional WHERE clauses is advised.

Reference: Building a Keyset from any field

5
  • Thanks a lot. I have around 20,000 records that I need to pull even after using WHERE clauses, Is it safe to use Aggregate queries to pull around 15 - 20k records ? Jan 7, 2023 at 0:42
  • should be OK but use execute anonymous and try!
    – cropredy
    Jan 7, 2023 at 2:10
  • I did do peformance analysis with this code: List<Account> accList = [SELECT Id, Name FROM Account LIMIT 10000]; List<String> names = new List<String>(); for(Account a:accList) { names.add(a.Name); } System.debug('Time: '+ Limits.getCPUTime()); Output : Time: 530 _________________________ Set<String> uniqueNames = new Map<String,SObject> ( [SELECT Name Id FROM Account Group By Name LIMIT 10000] ).keySet(); System.debug('Time: '+ Limits.getCPUTime()); Output: Time: 112 So using Aggregate is better than running a for loop in this scenario. Thanks a lot Jan 7, 2023 at 4:33
  • Yes, obviously as the aggregate queries are optimized to use the Salesforce underlying database handlers at platform level and automatically takes care of plugging the Name in <String, sObject> by hashMap, rather than when you iterate them separately using a for loop, you are just relying on the for-loop iterative optimizations. Very good observation. Jan 7, 2023 at 8:20
  • as a service to the community you should accept either Derek's or my answer if you're satisfied (use the check mark to the left of the answer)
    – cropredy
    Jan 7, 2023 at 18:49
2

No, there isn't really any other solution than to use a loop. SOQL returns SObjects by design and we can't modify that.

Even if you use the AggregateResult aliasing trick (which is probably not possible with a general string field like Name), there's still a loop running behind the scenes.

Loops are the way to handle collections of data. About the only suggestion that could be made here is to use a SOQL for loop instead of storing the results of the query in a separate list that you then feed into your loop.

1
  • 1
    Clarification: The SOQL for loop approach is better from a "lines of code" and heap space standpoint (SOQL for loops internally operate on 200 records at a time, so you aren't trying to keep all of the results in the heap). Useful when you don't need the SObject records later in code. Based on some writing by James from Joys of Apex on writing performant tests (no affiliation), getting an iterator instance and using a while loop is the approach for fast execution.
    – Derek F
    Jan 6, 2023 at 14:51

You must log in to answer this question.

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