MySQL — удаление дубликатов и сохранение ценных данных?

Сценарий: у меня есть несколько повторяющихся контактов в таблице. Дубликаты идентифицированы, я могу просто удалить их, но проблема в том, что я не хочу потерять данные, которые могут быть у дубликата, а у оригинала нет. Какие-нибудь советы?

Пример данных :

ID Name Email School Dupe_Flag Key
1  AAA  a@a          X         1 
2  AAB        JKL              1
3  BBB  b@b   MNO    X         2
4  BBC                         2

Желаемый результат:

ID Name Email School Dupe_Flag Key
1  AAA  a@a          X         1 
2  AAB  a@a   JKL              1
3  BBB  b@b   MNO    X         2
4  BBC  b@b   MNO              2

Как связаны две записи? : Они оба имеют одно и то же ключевое значение, и только один столбец имеет Dupe_Flag SET, который является дублирующим столбцом.

В приведенном выше случае ID 1 будет удален, но информация электронной почты из ID 1 должна быть применена к ID 2.

Что такое данные? : У меня несколько сотен строк и несколько 100 дубликатов. Инструкция UPDATE для каждой строки громоздка и невыполнима.

Бизнес-правила для определения того, какие данные имеют приоритет:

Если в столбце из исходной/хорошей записи (Dupe_Flag НЕ установлен) нет данных и если в соответствующем столбце записи Dupe (имеющем то же значение ключа) есть данные, то этот столбец исходной записи следует обновить.

Любая помощь/скрипт действительно ценится! Спасибо ребята :)


person ThinkCode    schedule 24.02.2010    source источник
comment
как мы можем увидеть, какие строки вы считаете дубликатами? как мы можем узнать, какие столбцы в дубликатах вы считаете более ценными, чем соответствующий столбец в строке, которую вы хотите сохранить? - без спецификации нельзя автоматизировать операцию.   -  person Roland Bouman    schedule 25.02.2010
comment
Сначала вам нужно определить свои собственные бизнес-правила для определения того, какие данные имеют приоритет в случае конфликта.   -  person Dolph    schedule 25.02.2010
comment
Dupe_Flag указывает, что это дубликат. Какие данные имеют приоритет? - Действительно просто. Если какой-либо из столбцов исходной (хорошей) записи равен NULL и если те же столбцы НЕ NULL в записи-дубликате, мы просто обновляем эти столбцы. Обновил мой вопрос для ясности. Благодарю вас!   -  person ThinkCode    schedule 25.02.2010


Ответы (4)


Предполагая, что пустые значения равны нулю, что-то вроде этого должно выводить нужные данные:

SELECT
  a.ID,
  IF(a.DupeFlag IS NULL, IF(a.Name IS NULL, b.Name, a.Name), a.Name) AS Name,
  IF(a.DupeFlag IS NULL, IF(a.Email IS NULL, b.Email, a.Email), a.Email) AS Email,
  IF(a.DupeFlag IS NULL, IF(a.School IS NULL, b.School, a.School), a.School) as School,
  a.DupeFlag,
  a.key
FROM
  table a,
  table b
WHERE
  a.Key = b.Key AND
  a.ID != b.ID
GROUP BY
  a.ID

Обратите внимание, что включить это в инструкцию UPDATE довольно просто.

person Benoît Vidis    schedule 26.02.2010
comment
Большое спасибо! Мой вопрос остается, потому что это всего лишь пример данных, на самом деле у меня есть сотни столбцов, поэтому операторы UPDATE для каждого из них не помогут :( Еще раз спасибо! - person ThinkCode; 26.02.2010

Я не знаю особенностей этой проблемы, но, вероятно, лучше избежать этой проблемы, установив столбцы в «уникальные», поэтому, если запрос попытается создать дубликат, он потерпит неудачу. Я думаю, что элегантное решение этой проблемы состоит в том, чтобы избежать ее в момент ввода данных.

Мне нравится использовать этот запрос для отслеживания дубликатов:

select * from table group by `Email` having count(Email) > 1
person rook    schedule 24.02.2010
comment
Это просто примерные данные. Теперь у меня есть ключи на месте, просто у некоторых контактов разные отчества и, следовательно, программными средствами мы не можем обнулить дюп. Только ручная проверка может определить, отсюда и проблема :( Кстати, я установил адрес электронной почты уникальным, данные примера были просто для иллюстрации. Спасибо.. - person ThinkCode; 25.02.2010
comment
Только ручной просмотр подскажет (или позволит угадать), какие данные более верны. С разными отчествами, как правильно? Программа не узнает. А изредка, по крайней мере на вашем примере, хоть и похоже на дубликат, но на самом деле это отдельная запись (два человека с одинаковым именем). - person thursdaysgeek; 25.02.2010
comment
Поверьте мне, ребята, у нас есть проверка на обнаружение дубликатов. Все, что я хочу знать, это самый простой/эффективный способ спасти данные, связанные с дублирующей записью. - person ThinkCode; 25.02.2010

Хотя это использует кучу вложенных SELECTS и на самом деле не является полным решением, оно должно либо вызвать что-то еще, либо, возможно, подтолкнуть в правильном направлении.

select * from 
  (select r1.ID,r1.Name,coalesce(r1.Email,r2.Email) as Email,
  coalesce(r1.School,r2.School) as School,r1.Dupe_Flag,r1.Key from 
  (select * from test1 where Dupe_Flag IS NULL) as r1  left outer join 
  (select * from test1 where Dupe_Flag IS NOT NULL) as r2 on r1.KEY=r2.Key) 
as results

Урожайность:

ID  Name  Email  School  Dupe_Flag  Key
2   AAB   a@a    JKL     NULL       1
4   BBC   b@b    MNO     NULL       2

На основе данных вашего примера.

person furrymitn    schedule 25.02.2010
comment
Благодарю вас! На самом деле я пытался устранить необходимость в запросах по каждому столбцу, поскольку в реальных данных было так много столбцов. До сих пор идеальным решением был бы сценарий PYTHON, который хранит все столбцы в массиве, проверяет любые ценные данные и обновляет исходный столбец. - person ThinkCode; 26.02.2010
comment
Приведенное ниже решение от Бенуа Видиса дает именно то, что вы ищете. - person furrymitn; 26.02.2010

Строки уникальны, так что проблем нет. Пожалуйста, перепроверьте данные вашего примера.

person pete    schedule 25.02.2010