function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
jd_06jd_06 

SOQL in loop unavoidable?

Hello - I need some assistance from the great minds in the SFDC dev community.  I've been asked to automatically add the count of Opportunity Team Members to a field on the Opportunity (basically just a roll-up).  For the most part this can't be done declaratively, so created a trigger.  The Non-Bulkified version of the trigger is very simple.  However, I can't see a way with collections (maps, lists, etc.) to bulkify it and keep my SOQL out of the For Loop.  Can anyone offer any ideas or suggestions as to how I could bulkify and keep the query out of a loop?  Here is my trigger code.


Thank you very much!
Jason

trigger CountOppTeam on OpportunityTeamMember (after insert, after delete)
{
List<Opportunity> oppList = new List<Opportunity>();
set<Id>oppIds = new set<Id>();

if(Trigger.isInsert || Trigger.isUpdate)
{
  List<id> oppId = new List<id>();
  for (OpportunityTeamMember oppTm: trigger.new)
  {
   oppIds.add(oppTm.OpportunityId);
  }

  for(Opportunity o: [Select id, CountTeamMembers__c From Opportunity Where id IN: oppIds])
  {
   List<OpportunityTeamMember> oppTmList = [Select id, Opportunityid From OpportunityTeamMember Where Opportunity.id =: o.id];
   o.CountTeamMembers__c = oppTmlist.Size();
   oppList.add(o);
  }

  update oppList;
}
else if (Trigger.isDelete)
{
  List<id> oppId = new List<id>();
  for (OpportunityTeamMember oppTm: trigger.old)
  {
   oppIds.add(oppTm.OpportunityId);
  }

  for(Opportunity o: [Select id, CountTeamMembers__c From Opportunity Where id IN: oppIds])
  {
   List<OpportunityTeamMember> oppTmList = [Select id, Opportunityid From OpportunityTeamMember Where Opportunity.id =: o.id];
   o.CountTeamMembers__c = oppTmlist.Size();
   oppList.add(o);
  }

  update oppList;
}
}
Best Answer chosen by jd_06
Avidev9Avidev9
Well you can use the nested SOQL (Parent to Child (http://www.salesforce.com/us/developer/docs/dbcom_soql_sosl/Content/sforce_api_calls_soql_relationships.htm))

for(Opportunity o: [Select id, CountTeamMembers__c,(Select id, Opportunityid From OpportunityTeamMembers ) From Opportunity Where id IN: oppIds])
  {
   List<OpportunityTeamMember> oppTmList o.OpportunityTeamMembers;
   o.CountTeamMembers__c = oppTmlist.Size();
   oppList.add(o);
  }

Please check the relationship name for  "OpportunityTeamMembers"

All Answers

Avidev9Avidev9
Well you can use the nested SOQL (Parent to Child (http://www.salesforce.com/us/developer/docs/dbcom_soql_sosl/Content/sforce_api_calls_soql_relationships.htm))

for(Opportunity o: [Select id, CountTeamMembers__c,(Select id, Opportunityid From OpportunityTeamMembers ) From Opportunity Where id IN: oppIds])
  {
   List<OpportunityTeamMember> oppTmList o.OpportunityTeamMembers;
   o.CountTeamMembers__c = oppTmlist.Size();
   oppList.add(o);
  }

Please check the relationship name for  "OpportunityTeamMembers"
This was selected as the best answer
James LoghryJames Loghry
You sure can do this without nested loops.  You can use a map, but the easiest way is to use a subquery to return the OpportunityLineItems associated with the Opportunity. I've provided an example below:

for(Opportunity o : 
    [Select 
        Id
        ,CountTeamMembers__c
        ,(Select Id From OpportunityTeamMembers) 
     From 
        Opportunity 
    Where 
        Id IN: oppIds]){
    o.CountTeamMembers__c = o.OpportunityTeamMembers.size();
    oppList.add(o);
}

For more on subqueries and how they can help you with other queries see here: http://www.salesforce.com/us/developer/docs/dbcom_soql_sosl/Content/sforce_api_calls_soql_relationships.htm

Also, Kevin Poorman and I are giving a talk on Apex 10 Commandments at Dreamforce this year.  So if you're coming, you might want to check that out.  (You can also find the same session from last year on youtube)
James LoghryJames Loghry
Sorry, I mistyped, I meant OpportunityTeamMembers, not OpportunityLineItems earlier.
jd_06jd_06
You guys rock!!  Tried both suggestions and both worked flawlessly!  Thank you both for quick answers, I wish I could select both of yours as best answers.

James, I have a note to sign-up for your Dreamforce session.  Looking forward to it.

Thanks again guys.
Jason