I have an ordered list of a custom object which is the child of a different object. I want to get the earliest date of the child object per parent object. Here is a basic example:

List<objB__c> relChild = [SELECT id, objA__c, date 
                              FROM objB__c 
                              WHERE objA__c IN: objASet
                              ORDER BY date NULLS LAST];

So I should have a list of all children (objB) for any parent (objA) that I already have in a Set I had created earlier. Almost all the time there will only be one record in objASet, but I am trying to "bulkify" my code and allow it to handle multiple records just in case.

How can I pull the earliest date field from my list for each objA? Can I create a Map of id,Date and just iterate through the list? Or do I have to create a wrapper? Or can I use the sort method in some way?

Here is my idea for just doing a simple iteration:

Map<id,date> firstDate = new Map<id,date>();
    for(objB__c b: relChild){
        if(firstDate.containsKey(b.objA__c){} else {
            firstDate.put(b.objA__c, date); //would this get me the first date for each objA__c?
  • 1
    Just negate the clause rather than using an empty if block...
    – Adrian Larson
    May 7 '18 at 16:20
  • ...by that you mean just add ! to the front?
    – Chance
    May 7 '18 at 16:22
  • 1
    Indeed. But you don't even need conditionals if you use aggregate queries.
    – Adrian Larson
    May 7 '18 at 16:23

I recommend you just use aggregate queries here. You can then get just one row for each mapping you're trying to create. You could even do the nifty alias to Id trick so you can use the built in Map constructor.

Map<Id, AggregateResult> minDates = new Map<Id, AggregateResult>([
    SELECT Lookup__c Id, MIN(Date_Field__c) earliest FROM Child__c GROUP BY Lookup__c

Then, if you have an Id for your parent, you can just do:

AggregateResult aggregate = minDates.get(parent.Id);
Date earliest = (aggregate == null) ? null : (Date)aggregate.get('earliest');

Just to note, your approach would work, but it is more clear and efficient to simply negate your clause.

if (!myMap.containsKey(...))
  • This is very helpful, thank you. I don't understand the syntax of the last line, though. What does the (aggregate == null) ? null do?
    – Chance
    May 7 '18 at 16:27
  • 1
    It's a ternary operator. It's the same as Date earliest; if (aggregate != null) earliest = (Date)aggregate.get('earliest');.
    – Adrian Larson
    May 7 '18 at 16:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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