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
Michael Hedrick 2Michael Hedrick 2 

Merge duplicate Leads and related records

Hello All,
I have been tasked to find duplicate Leads within our org.

Each Lead has an activity(s)
FInd the oldest lead and make this the master.
Take the activities from the other Leads and merge them to the Master Lead. 
Delete the duplicate Leads.

This wil be a once and done since we now have a process to marry all the Leads together based on the email address.
I just need some help on the best approach to resolve this issue.
I do not actually need to merge the vlaues on the Lead details record as much as I need to make sure I get all of the Activities into a single Leads record.

I thought about trying the below approach but I am not thinking it will meet all of me needs
List<AggregateResult> DuplicateList = 
[select count(email), id from lead where email != '' group by id having count(email) >1 limit 200];


For (AggregateResult Agm:DuplicateList){

   String LeadEmail = string.valueOf(agm.get('email'));
   Lead ToLead = [Select id, email from Lead where email like :LeadEmail limit 1];
   Lead FromLead = [Select id, email from Lead where Id != :ToLead.Id and email like :LeadEmail Limit 1];

   system.debug(LoggingLevel.Info,'*** FromLead: ' + FromLead.email+' ('+FromLead.Id+')');
   system.debug(LoggingLevel.Info,'*** ToLead  : ' + ToLead.email+' ('+ToLead.Id+')');
   database.merge(ToLead , FromLead );

}
Thanks,
M
 
Best Answer chosen by Michael Hedrick 2
Adilson Arcoverde JrAdilson Arcoverde Jr
Hi Michale,

Could you try this code?
List<Lead> leads = [Select Id, Email, (Select Id, WhoId from Tasks), (Select Id, WhoId from Events) from Lead ORDER BY CreatedDate];

Map<String,List<Lead>> leadsMap = new Map<String,List<Lead>>();

for( Lead l : leads ) {
    if( !leadsMap.containsKey( l.Email ) ) {
        leadsMap.put( l.Email, new List<Lead>() );
    }

    leadsMap.get( l.Email ).add( l );
}

List<Event> eventsToUpdate = new List<Event>();
List<Task> tasksToUpdate = new List<Task>();
List<Lead> leadsToDelete = new List<Lead>();


for( String email : leadsMap.keySet() ) {
    List<Lead> leadsToMerge = leadsMap.get( email );
    if( leadsToMerge.size > 1 ) {
        Lead masterLead = leadsToMerge[0];

        for( Integer i = 1; i < leadsToMerge.size(); i++ ) {
            Lead mergedLead = leadsToMerge[index];
            for( Task t : mergedLead.Tasks ) {
                t.WhoId = masterLead.Id;
                tasksToUpdate.add( t );
            }

            for( Event e : mergedLead.Event ) {
                e.WhoId = masterLead.Id;
                eventsToUpdate.add( e );
            }
            leadsToDelete.add( mergedLead );
        }

    }
}

if( eventsToUpdate.size() > 0 ) update eventsToUpdate;
if( tasksToUpdate.size() > 0 ) update tasksToUpdate;
if( leadsToDelete.size() > 0 ) delete leadsToDelete;

Hope you find this solution useful. If it does please mark as Best Answer to help others developers too.

Regards.

All Answers

Adilson Arcoverde JrAdilson Arcoverde Jr
Hi Michale,

Could you try this code?
List<Lead> leads = [Select Id, Email, (Select Id, WhoId from Tasks), (Select Id, WhoId from Events) from Lead ORDER BY CreatedDate];

Map<String,List<Lead>> leadsMap = new Map<String,List<Lead>>();

for( Lead l : leads ) {
    if( !leadsMap.containsKey( l.Email ) ) {
        leadsMap.put( l.Email, new List<Lead>() );
    }

    leadsMap.get( l.Email ).add( l );
}

List<Event> eventsToUpdate = new List<Event>();
List<Task> tasksToUpdate = new List<Task>();
List<Lead> leadsToDelete = new List<Lead>();


for( String email : leadsMap.keySet() ) {
    List<Lead> leadsToMerge = leadsMap.get( email );
    if( leadsToMerge.size > 1 ) {
        Lead masterLead = leadsToMerge[0];

        for( Integer i = 1; i < leadsToMerge.size(); i++ ) {
            Lead mergedLead = leadsToMerge[index];
            for( Task t : mergedLead.Tasks ) {
                t.WhoId = masterLead.Id;
                tasksToUpdate.add( t );
            }

            for( Event e : mergedLead.Event ) {
                e.WhoId = masterLead.Id;
                eventsToUpdate.add( e );
            }
            leadsToDelete.add( mergedLead );
        }

    }
}

if( eventsToUpdate.size() > 0 ) update eventsToUpdate;
if( tasksToUpdate.size() > 0 ) update tasksToUpdate;
if( leadsToDelete.size() > 0 ) delete leadsToDelete;

Hope you find this solution useful. If it does please mark as Best Answer to help others developers too.

Regards.
This was selected as the best answer
Michael Hedrick 2Michael Hedrick 2
Hello Adilson,
This worked well thank you very much. 
Just a note to others using the code you modify line 20 toif( leadsToMerge.size() > 1 )
and  line 24 to Lead mergedLead = leadsToMerge[i];

I think I am going to add other related records form the leads like email results and opportunities and hopefully I can get the email and campaign information.
If I choose not to delete the merged leads and instead uncheck the flag on the new parent Lead(users concern with automatically deleting records) where in teh code are you determining the parent? 

Also, there are over 800K leads.  If I can only 50K records at a time I am assuming this would need to be edited to run as a batch ?

Thanks you,
M