Salesforce Rollup Summary on Lookup Relationship (Complete Guide)

In Salesforce, managing data between related objects is very important. Many times, we need to calculate values from child records and display them on the parent record.

For example, you may want to count the number of contacts associated with an account or calculate the total number of opportunities.

Salesforce provides a feature called a roll-up summary field to solve this problem. However, this feature works only when the objects are connected using a master-detail relationship.

When objects are connected using a lookup relationship, Salesforce does not allow creating roll-up summary fields directly.

In Salesforce, the sales team was using the sales application and wanted to display the total number of contact records related to each account directly on the account record, similar to a roll-up summary field.

But, in Salesforce, accounts and contacts have a lookup relationship, not a master-detail relationship. Salesforce does not allow creating roll-up summary fields on lookup relationships.

As a Developer, I was required to build a custom solution to calculate and display the number of contacts for each account, which functions similarly to a rollup summary field.

In this tutorial, we will learn how to create a rollup summary on a lookup relationship using Salesforce Apex Triggers. After that, whenever a contact is inserted, updated, deleted, or undeleted, the trigger automatically updates the count on the related account.

What is a Roll-Up Summary Field in Salesforce?

A roll-up summary field is used to calculate values from related child records and display the result on the parent record. These calculations can include:

  • Count of records
  • Sum of values
  • Minimum value
  • Maximum value

For example:

  • Count total contacts on an account
  • Sum of opportunity amounts
  • Maximum order value

This feature is very powerful because it automatically updates values when data changes.

Can We Create a Rollup Summary Field on a Lookup Relationship Object in Salesforce?

No, there is no direct way to create a Salesforce rollup summary field on a lookup relationship; it can only be created on a master-detail relationship

To achieve a similar functionality with a lookup, we must use an Apex trigger, Salesforce Flow, or a third-party AppExchange application, such as a rollup helper or declarative lookup rollup summaries (DLRS). 

In the steps below, I will demonstrate what happens when we try to create a rollup summary field on an object with a lookup relationship.

Here, I will create a custom roll-up summary field on the account object that displays the total number of contact records associated with that account.

For that, go to the Gear Icon. -> Click on the Setup. -> Select the Object Manager tab. Select the Object on which you want to create the Rollup Summary Field. Here, I’m going to create an Account Object.

In the account setup, click Fields and Relationships, then click the New button to create a new field.

In this step, since we want to display the count of contacts related to an account object, we will select the Rollup Summary option from the data type and click Next.

Salesforce Rollup Summary Field on Lookup Rlationship

Next, provide the Field Label and API Name for the rollup summary field, then click Next.

Rollup Summary Without Master Detail Relationship in Salesforce

Next, we would normally select the Summarized Object from which we want to summarize the data. In our case, the object would be Contact, since we want to count the number of Contacts associated with an Account.

However, because Account and Contact are in a Lookup relationship (not a Master-Detail relationship), the contact object does not appear in the list of available summarized objects when creating a rollup summary field.

Master Object in Rollup Summary FIeld in Salesforce

Create Rollup Summary on Lookup Relationship Using Salesforce Apex Trigger

Since we cannot create a standard rollup summary field on a lookup relationship directly, we will write an Apex Trigger on the Contact object and implement the business logic into a Helper Class.

The first step is to create a custom Number field on the Account object to display the total number of related Contacts. Let’s name this field Total_Contacts__c.

This field will function as a roll-up summary field, but instead of being automatically updated by Salesforce, it will be updated by our Apex Trigger logic whenever any Contact record is inserted, updated, deleted, or undeleted.

Create Custom Number Field in Salesforce

First, we will create a Helper Class to implement the logic that calculates the number of Contact records related to an Account and updates the custom field (Total_Contacts__c) on the Account record.

To create the class, go to Setup → Developer Console -> File -> New -> Apex Classes → and then write the Apex class with the required logic.

In the method, I declared a List collection that retrieves the contact records from the trigger, and then we use this List to store both new and old contact records.

After that, we use a for loop to iterate over the Account records stored in the list. To get only unique records, we store them in a Set.

Then, using a Map collection, we mapped the Account Name to the corresponding Account record in Salesforce, which we retrieved using a SOQL query. That means we are creating a key-value pair.

Next, using the COUNT() operator in a SOQL query, we will calculate the total number of Contact records per Account.

After fetching this count, we will update the custom Number field (Total_Contacts__c) on the Account object to always display the correct number of related Contacts.

public class ContactTriggerHandler {

    public static void updateContactCount(List<Contact> newList, List<Contact> oldList, Boolean isDelete) { 

        //Declare the variable first
        Set<Id> accountIds = new Set<Id>();

        // Collect Account Ids from new records
        if(newList != null){
            for(Contact con : newList){
                if(con.AccountId != null){
                    accountIds.add(con.AccountId);
                }
            }
        }

        // Collect Account Ids from old records (for deletes/updates)
        if(oldList != null){
            for(Contact con : oldList){
                if(con.AccountId != null){
                    accountIds.add(con.AccountId);
                }
            }
        }

        if(accountIds.isEmpty()){
            return; // nothing to process
        }

        // Count Contacts for each Account
        Map<Id, Integer> accountContactCount = new Map<Id, Integer>();
        for(AggregateResult ar : [
            SELECT AccountId, COUNT(Id) totalContacts
            FROM Contact
            WHERE AccountId IN :accountIds
            GROUP BY AccountId
        ]){
            accountContactCount.put((Id)ar.get('AccountId'), (Integer)ar.get('totalContacts'));
        }

        // Update Account with Contact count
        List<Account> accountsToUpdate = new List<Account>();
        for(Id accId : accountIds){
            Account acc = new Account(Id = accId);
            acc.Total_Contacts__c = accountContactCount.containsKey(accId) ? accountContactCount.get(accId) : 0;
            accountsToUpdate.add(acc);
        }

        if(!accountsToUpdate.isEmpty()){
            update accountsToUpdate;
        }
    }
}
Rollup Summary Field on Lookup Relationship Objects

In the trigger below, we have defined the object on which the trigger is created and the trigger events that will fire the logic. Here, the trigger is defined on the Contact object and runs after insert, update, delete, and undelete.

These events are required because any of these operations can change the number of contacts associated with an account, and we want the count on the Account to stay up to date.

Then, using the helper class name, call the methods in the order you want to execute.

trigger ContactTriggers on Contact (after insert, after update, after delete, 
                                                                                                                                                             after undelete) {
      if(Trigger.isAfter){

                 if(Trigger.isInsert || Trigger.isUpdate || Trigger.isDelete || Trigger.isUndelete){

                              ContactTriggerHandler.updateContactCount(Trigger.new, Trigger.old, 
                                                                                                                                                           Trigger.isDelete);
        }
    }
}
Create Apex Trigger to Create Rollup Summary on Lookup Relationship in Salesforce

Proof of concept:

In the screenshot below, you can see in the Related tab of the Account record, under the contacts section, four existing Contact records are related to the Agro Tech Account.

Salesforce Lookup Relationship Rollup Summary

As you open the Detail tab, the custom field Total_Contacts__c on the account displays a value of 4, because our trigger has automatically counted the related contacts and updated the field.

Create Rollup Summary on Lookup Relationship Using Salesforce Apex Trigger

In this way, we can create a rollup summary on a lookup relationship using Salesforce Apex Trigger.

Frequently Asked Questions

Q1: Can we create a roll-up summary on the lookup?

No, not directly

Q2: What is the best method?

1. Apex for developers
2. DLRS for admins

Q3: Is Flow good for roll-up?

Yes, for simple use cases

Conclusion

Roll-up summary fields are very useful in Salesforce, but they work only with master-detail relationships. When working with lookup relationships, we need to use alternative approaches such as Apex triggers, Flow, or DLRs.

Among these methods, Apex provides the most flexibility, while Flow and DLRS provide easier solutions for admins. By understanding these approaches, you can implement roll-up logic in any real-time Salesforce project.

You may like to read:

Agentforce in Salesforce

DOWNLOAD FREE AGENTFORCE EBOOK

Start with AgentForce in Salesforce. Create your first agent and deploy to your Salesforce Org.

Salesforce flows complete guide

FREE SALESFORCE FLOW EBOOK

Learn how to work with flows in Salesforce with 5 different real time examples.