trigger setCertificationToFailed on Exam__c (after update) {
     List<Exam__c> ExamList = new List<Exam__c>();
     ExamList = [SELECT Id, Exam_id__c, Exam_state__c, doNothingExam__c, Certification__r.Id, Certification__r.Exam_state__c, Certification__r.Name FROM Exam__c 
                 WHERE Exam_state__c in ('Failed') AND Certification__r.Exam_state__c in ('Active') AND doNothingExam__c = True];

I need to identify if each row inside this List share similar values with other rows of the same list.

eg. Row 1 => Certification__r.Id = ABCD, Exam_id__c = 1234, Row 2 => Certification.Id = EFGH, Exam_id__c = 0000, Row 3 => Certification.Id = ABCD, Exam_id__c = 1234

Above Row 1 and 3 have same Certification__r.Id, Exam_id__c. How can I identify this through a code?.

Note that only Certification__r.Id, Exam_id__c should be compared with every row. If both of them match together with another row, then it should change Certification__r.Exam_state__c to 'FAILED' from 'Active'

Below in this picture, you can notice similar rows with similar Certification__r.Id, Exam_id__c values.

Query run on Developer Console

  • 1
    Please, explain, if Row 1 => Certification__r.Id = ABCD, Exam_id__c = 1234 and Row 2 => Certification__r.Id = ABCD, Exam_id__c = 5678 Would they count as same for you? Or should they have in common both certification id and exam id? – Mariia Illarionova Mar 28 '19 at 9:37
  • hi @MariiaIllarionova they should have only Certification__r.Id, Exam_id__c in common. then depending on that, i should update field Certification__r.Exam_state__c to 'failed' from active. Please see my updated image – Niveth Kumar Mar 28 '19 at 9:39
  • when both Certification__r.Id, Exam_id__c are equal, it will count as same @MariiaIllarionova it doesn't count when either one of it is different. hope i answered your question, thanks – Niveth Kumar Mar 28 '19 at 9:50

Here is the solution:

List<Exam__c> exams = new List<Exam__c>();
exams = [
        SELECT Id, Exam_id__c, Exam_state__c, doNothingExam__c, Certification__r.Id, Certification__r.Exam_state__c, Certification__r.Name 
        FROM Exam__c];

//here we are formatting the map to identify duplicates
Map<String, List<Exam__c>> toCheck = new Map<String, List<Exam__c>>();
Set<Id> certificationIds = new Set<Id>();

for (Exam__c exam_i : exams) {
    String validationString = exam_i.Exam_id__c + exam_i.Certification__r.Id;
    if (!toCheck.containsKey(validationString)) {
        toCheck.put(validationString, new List<Exam_c>());

    toCheck.put(validationString, toCheck.get(validationString).add(exam_i));

Map<Id, Certification__c> certificationMap = new Map<Id, Certification__c>([SELECT Id, Exam_state__c FROM Certification__c WHERE Id IN :certificationIds]);

//here we are updating statuses
for (List<Exam__c> examList_i : toCheck.values()) {
    if (examList_i.size() > 1) {
        for (Integer i = 1; i < examList_i.size() ; i++) {
            Certification__c tmp = certificationMap.get(examList_i[i].Certification__r.Id);
            tmp.Exam_state__c = 'FAILED';
            certificationMap.put(examList_i[i].Certification__r.Id, tmp);

update certificationMap.values();

Explanation: If both certification id and exam id are important to you, then combine them and save as map keys. Also you need to update Certification__c later in the code as I have written.

  • how will the code change if i add both the certification id and exam_id__c(string). Also certification id is an id, and exam_id__c is a string. please help – Niveth Kumar Mar 28 '19 at 9:55
  • 1
    Id easely converts to string when concatenating: String validationString = exam_i.Exam_id__c + exam_i.Certification__r.Id; If you're not sure, you can type: String validationString = String.valueOf(exam_i.Exam_id__c) + exam_i.Certification__r.Id; Then, how it will help you: 1234ABSD is the same with 1234ABCD from your example (Row 1 and Row 3), so the map will have 2 keys: 1234ABCD and 000EFGH, and the first key will correspond list with 2 exams. – Mariia Illarionova Mar 28 '19 at 10:01
  • 1
    You'll get all the values in the list except the first one ,and change corresponding certification states to failed, because the are duplicates. – Mariia Illarionova Mar 28 '19 at 10:01
  • 1
    Write it like this: List<Exam__c> tmp = toCheck.get(validationString); tmp.add(exam_i); toCheck.put(validationString, tmp); – Mariia Illarionova Apr 1 '19 at 9:42
  • 1
    With all my attitude I haven't gone through your code so far. My code is just an example how to get to the exact solution, any modifications you do are acceptable and wanted. Suit this code in any need. – Mariia Illarionova Apr 9 '19 at 7:19

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.