You can use a list of nicknames, like this one to find all contacts with a common name. Once you've found a list of "Andrew" first names, loop through each Andrew contact and find all of the "Andy" contacts plus "Andrew's" last name and email or phone number. From here, if you identify a duplicate, you can set the nickname for both contacts to the first name of the duplicate contact ("Andy") then run a Dedupe rule like this: Nickname + (Phone or Email). Here's the script I used to do this:
function setContactNicknames() {
$nicknames = explode("\n", file_get_contents(__DIR__ . '/nicknames.csv'));
foreach($nicknames as $rootNames) {
$rootNameFound = null;
$eachRoot = explode(',', $rootNames);
foreach($eachRoot as $nickname) {
if ($rootNameFound) {
foreach($rootNameFound['values'] as $rootContact) {
$nickMatch = null;
if ($rootContact['email']) {
$nickMatch = civicrm_api3('Contact', 'get', [
'sequential' => 1,
'first_name' => "{$nickname}",
'last_name' => $rootContact['last_name'],
'email' => $rootContact['email']
]);
}
if (!$nickMatch && $rootContact['phone']) {
$nickMatch = civicrm_api3('Contact', 'get', [
'sequential' => 1,
'first_name' => "{$nickname}",
'last_name' => $rootContact['last_name'],
'phone' => $rootContact['phone']
]);
}
if ($nickMatch && $nickMatch['count']) {
$matchContact = $nickMatch['values'][0];
$setNickname = $matchContact['first_name'];
if ($rootContact['contact_id'] !== $matchContact['contact_id']) {
civicrm_api3('Contact', 'create', [ 'id' => $rootContact['contact_id'], 'nick_name' => $setNickname, ]);
civicrm_api3('Contact', 'create', [ 'id' => $matchContact['contact_id'], 'nick_name' => $setNickname, ]);
echo $rootContact['first_name'] . ' ' . $rootContact['contact_id'] . ' ';
echo $matchContact['first_name'] . ' ' . $matchContact['contact_id'] . ' ';
}
}
}
} else {
$searchName = civicrm_api3('Contact', 'get', [ 'sequential' => 1, 'first_name' => "{$nickname}", ]);
if ($searchName['count']) {
$rootNameFound = $searchName;
}
}
}
}
}