0

I have below code ,but not able to understand how i can avoid second for loop inside account please suggest

    public static void getOpenCaseOnAccount() {
    Map<id,user> userIds = new map<id,user>([select id from user]);
    
    map<id,account> accountMap = new map<id,account>( [select id,createdbyid from account where createdbyid in :userIds.keyset()]);
    
    list<case> caseList =[select id,CaseNumber,accountid,Status from case where accountid in:accountMap.keyset()];
    
    map<id,case>caseMap = new map<id,case>();
    string caseNumbers='';
    for(account acc:accountMap.values()) {
        for(case c:caseList) {
            if(c.AccountId == acc.Id && c.status!='Closed' ){
                    caseNumbers += c.CaseNumber +'\n';
            }
        }
    }
    system.debug('caseNumber***'+caseNumbers);
}
6
  • 1
    See the I need data from indirectly related records based on one or more input record fields section in the above Q&A which demonstrates how to use maps for relating things together. – Phil W Jun 17 at 9:53
  • thanks phil W. in this example we can use nested query ,but in general as well if i wan to modify the above code to reduce the inside for loop..i just want to know how i can do that – Sandy Jun 17 at 9:57
  • like i tried Map<id,case>casemap= new map<id,case>() for(case cs: caseList) {csmap.put(cs.accountid,cs) – Sandy Jun 17 at 9:59
  • 1
    Look at the detail of the sample code in that other Q&A - it demonstrates how to convert things to maps and then use those maps to do quick lookup. This will allow you to avoid nested loops like you have (which won't scale). – Phil W Jun 17 at 9:59
  • 1
    Looking at your code, you don't actually need the outer account loop at all; just iterate over the caseList since you're guaranteed that the cases are only for the accounts in the accountMap anyway. You should also add the Status != 'Closed' to the query for cases so you can remove the if condition. – Phil W Jun 17 at 10:05
1

You don't need to do any maps here, at least with the sample code you have:

public static void getOpenCaseOnAccount() {
    Map<id,user> userIds = new map<id,user>([select id from user]);
    
    List<Account> accounts = [select id from account where createdbyid in :userIds.keyset()];
    
    List<Case> caseList =[select CaseNumber from case where accountid in :accounts AND Status != 'Closed'];

    string caseNumbers='';

    for(case c:caseList) {
        caseNumbers += c.CaseNumber +'\n';
    }

    system.debug('caseNumber***'+caseNumbers);
}

Note that I added the Status check to the Case query - why iterate cases that are not relevant? You don't need the Account map and can just use a list to directly get the Cases, then iterate those.

For other scenarios where you want to have a mapping, for example, from Account ID to all the Cases that match that Account ID, you could use maps like follows:

Map<Id, List<Case>> casesByAccountId = new Map<Id, List<Case>>();

// Iterate over the cases you have and put them into the map
for (Case case : cases) {
    List<Case> casesForAccount = casesByAccountId.get(case.AccountId);

    if (casesForAccount == null) {
        casesByAccountId.put(case.AccountId, new List<Case>{ case });
    } else {
        casesForAccount.add(case);
    }
}

This ensures you have all the cases matching a given Account ID, and you manage it in a very efficient manner. From that point on, when you have an Account ID you can simply get all the Cases for that Account ID from the map with casesByAccountId.get(accountId).

6
  • thanks phil W. but still i want to see how I can generate the map and avoid for loop ..that can be helpful in somewhere else. – Sandy Jun 17 at 10:11
  • Look at the bulkifying query code in the Q&A I pointed you at. It clearly shows how to use maps instead of loops. – Phil W Jun 17 at 10:12
  • sure.thanks phil W. great help – Sandy Jun 17 at 10:12
  • Hi Phil W. the link u provided is using map ,where // Note that in this contrived example we may have more than one case that matches // the Priority/ContactId combo. If so, this processing will keep the last Case matching // the given combination. It may be that you always have unique combinations for // your key values, you may want to use ORDER BY in the query to decide which to // keep or you may apply some other strategy for choosing which to keep, ................... – Sandy Jun 17 at 11:07
  • ..So in my case i am getting only one case per account which is the problem..can u suggest or show me example where i can iterate map<id,list<cases> – Sandy Jun 17 at 11:07

Not the answer you're looking for? Browse other questions tagged or ask your own question.