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
deanodeano 

Nested SOQL Queries. From Child, up to parent, and back down to other objects children

Hello, i'm new to salesforce/apex/soql, so any help would be muchly appreciated!

 

Scenario:

A custom object Program__c has  child events which represent program sessions. The program also has children of another custom object Participant__c that represents participants of the program. Participant__c is a junction object that looks up to the program and a contact.

 

I need to select out all events that are occuring in 3 days, and send out an email to all participants of the events program reminding them the event is up coming.

 

The only solution I could work out for this was to use cronkit (appexchange app) to poll for all relevent events at least daily, and in the cronkit trigger send emails using apex to the participants of the event.

 

I have all of this working. With the following code (I've left out irrelevent parts) which resides inside a cronkit trigger:

 

DateTime nowPlusThreeDays = Datetime.newInstance(Datetime.now().date(), Datetime.now().time()).addDays(3);

 

List<Event> events = [
     SELECT e.Description, e.Id, e.Location, e.WhatId, e.Subject, e.IsAllDayEvent, e.ActivityDateTime, e.EndDateTime, What.Id
     FROM Event e
     WHERE
      e.ActivityDateTime >= :dateTime.newInstance(nowPlusThreeDays.Year(),nowPlusThreeDays.month(),nowPlusThreeDays.day()) AND
      e.ActivityDateTime < :dateTime.newInstance(nowPlusThreeDays.date().Year(),nowPlusThreeDays.month(),nowPlusThreeDays.day(),23,59,59) AND
      e.RecordType.Name = 'Program Session' AND
      e.Participant_Reminder_Email_Sent__c = False
     LIMIT 100
    ];

 

EmailTemplate template = [SELECT ID FROM EmailTemplate WHERE (name = 'Program Participant Reminder') LIMIT 1];

 

for(Event event:events){

 

Program__c program = [SELECT Id, Name, (SELECT Participant__r.Name, Participant__r.Id FROM Junction_Objects__r) FROM Program__c WHERE Id = :event.WhatId LIMIT 1];

 

for(Junction_Object__c junction:program.Junction_Objects__r){
      Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
      mail.setTemplateId(template.Id);
      mail.setTargetObjectId(junction.Participant__r.Id);
     

emails.add(mail);
     }
     
     Messaging.sendEmail(emails);
     
     event.Participant_Reminder_Email_Sent__c = True;
     update event;
    }

 

The problem is I really need to get the second query (the one where I get the program info and the child junction objects) out of the for loop iterating through the selected events.

 

Cronkit has a limit of 20 soql queries, and it doesn't look very good anyway.

 

Could anyone please help me to modify my data queries so that they are not inside any loops. I tried but always got an error about the first sobject returned by a sub select being a child of the outer select. I understand that, but don't know how to get around the fact that I must first go up to the program and then down to the participants.

 

Thank you very much for any help!!!

 

Deano