Извините за задержку с ответом. Я был немного занят последние пару дней.
Ниже приведен мой ответ, основанный на следующих предположениях:
1) Вы будете устранять проблемы с написанием имен с помощью какого-либо другого механизма (вы упомянули, что вы будете очищать его с помощью регулярных выражений в комментарии к исходному вопросу).
2) Набор DUP может быть идентифицирован с использованием имени, фамилии и рождения (вы упомянули это в комментарии к исходному вопросу).
3) Имя, фамилия и рождение не могут быть NULL.
4) Вы не можете иметь более одной записи FIN в наборе DUP (вы упомянули это в комментарии к исходному вопросу).
Если какое-либо из вышеперечисленных предположений неверно, мой ответ необходимо будет изменить.
Ниже приведены шаги, которые необходимо предпринять:
1) Обновите все записи FIN, чтобы скопировать PersonalKey из записи не-FIN:
UPDATE Pruebas p1
INNER JOIN Pruebas p2
ON p1.Firstname = p2.Firstname
AND p1.Lastname = p2.Lastname
AND p1.Birth = p2.Birth
SET p1.PersonalKey = p2.PersonalKey
WHERE p1.Source like 'FIN%'
AND p1.PersonalKey is null
AND p2.PersonalKey is not null;
2) Удалить все не-FIN записи, где у нас есть FIN-запись:
DELETE p2
FROM Pruebas p1
INNER JOIN Pruebas p2
ON p1.Firstname = p2.Firstname
AND p1.Lastname = p2.Lastname
AND p1.Birth = p2.Birth
WHERE p1.Source like 'FIN%'
AND p2.Source not like 'FIN%';
На этом этапе все DUP с записью FIN были очищены, так что осталась только запись FIN.
3) Если мы решим остаться с записью DRV для всех остальных случаев. Нам нужно будет скопировать PersonalKey из другой записи в запись DRV:
UPDATE Pruebas p1
INNER JOIN Pruebas p2
ON p1.Firstname = p2.Firstname
AND p1.Lastname = p2.Lastname
AND p1.Birth = p2.Birth
SET p1.PersonalKey = p2.PersonalKey
WHERE p1.Source like 'DRV%'
AND p1.PersonalKey is null
AND p2.PersonalKey is not null;
4) Удалить все записи без DRV, где у нас есть запись DRV:
DELETE p2
FROM Pruebas p1
INNER JOIN Pruebas p2
ON p1.Firstname = p2.Firstname
AND p1.Lastname = p2.Lastname
AND p1.Birth = p2.Birth
WHERE p1.Source like 'DRV%'
AND p2.Source not like 'DRV%';
В этот момент все DUP с записью DRV были очищены, так что осталась только запись DRV.
Если единственным другим типом записи является запись SA, то больше не должно быть DUP, и мы закончили.
5) Если мы хотим выбрать запись с наибольшим количеством заполненной информации, или если мы закончили 3 и 4, и остается более одного типа записи, вызывающей DUP. Нам нужно скопировать PersonalKey из любой записи в наборе DUP, которая имеет его, в любую запись, которая не имеет его для всех не-FIN записей:
UPDATE Pruebas p1
INNER JOIN Pruebas p2
ON p1.Firstname = p2.Firstname
AND p1.Lastname = p2.Lastname
AND p1.Birth = p2.Birth
SET p1.PersonalKey = p2.PersonalKey
WHERE p1.Source not like 'FIN%'
AND p1.PersonalKey is null
AND p2.PersonalKey is not null;
6) Удалить все записи, кроме той, которая содержит наибольшее количество информации (как определено в вычисляемом столбце info_score):
DELETE p5
FROM Pruebas p5
INNER JOIN (SELECT p3.Firstname
, p3.Lastname
, p3.Birth
, MIN(p3.Id) AS min_id
FROM Pruebas p3
INNER JOIN (SELECT p1.Firstname
, p1.Lastname
, p1.Birth
, count(*) AS c
, MAX((p1.Name is not null) + (p1.RFC is not null) + (p1.Source is not null) + (p1.PersonalKey is not null)) AS info_score
FROM Pruebas p1
GROUP BY p1.Firstname
, p1.Lastname
, p1.Birth
HAVING count(*) > 1) p2
ON p3.Firstname = p2.Firstname
AND p3.Lastname = p2.Lastname
AND p3.Birth = p2.Birth
AND ((p3.Name is not null) + (p3.RFC is not null) + (p3.Source is not null) + (p3.PersonalKey is not null)) = p2.info_score
GROUP BY p3.Firstname
, p3.Lastname
, p3.Birth) p4
ON p4.Firstname = p5.Firstname
AND p4.Lastname = p5.Lastname
AND p4.Birth = p5.Birth
AND p4.min_id <> p5.Id;
В этот момент все DUP были свернуты с сохранением PersonalKey, если он был доступен, и записями FIN были сохранены, если они существовали, в противном случае была сохранена либо запись DRV, либо запись с наибольшим количеством информации.
Дайте мне знать, если у вас есть какие-либо вопросы по любому из перечисленных вопросов.
Надеюсь, это поможет,
-Dipin