Поиск и работа с дублированными пользователями - PullRequest
16 голосов
/ 03 марта 2012

В большой базе данных пользователей со следующим форматом и примерами данных мы пытаемся идентифицировать дублированных людей:

id   first_name    last_name   email
---------------------------------------------------
 1   chris         baker       
 2   chris         baker       chris@gmail.com
 3   chris         baker       chris@hotmail.com
 4   chris         baker       crayzyguy@crazy.com  
 5   carl          castle      castle@npr.org
 6   mike          rotch       fakeuser@sample.com  

Я использую следующий запрос:

SELECT 
    GROUP_CONCAT(id) AS "ids",
    CONCAT(UPPER(first_name), UPPER(last_name)) AS "name",
    COUNT(*) AS "duplicate_count" 
FROM 
    users 
GROUP BY 
    name 
HAVING 
    duplicate_count > 1

Это прекрасно работает; Я получаю список дубликатов с номерами идентификаторов соответствующих строк.

Мы переназначим любые связанные данные, связанные с дубликатом, фактическому человеку (set user_id = 2 where user_id = 3), затем удалим дублирующую строку пользователя.

Проблема возникает после того, как мы делаем этот отчет в первый раз, поскольку мы очищаем список после ручной проверки того, что они действительно являются дубликатами - некоторые НЕ являются дубликатами. Есть 2 Криса Бейкерса, которые являются законными пользователями.

Мы не хотим продолжать видеть Криса Бейкера в последующих повторяющихся отчетах до конца времени, поэтому я ищу способ пометить, что идентификатор пользователя 1 и идентификатор 4 НЕ являются дубликатами друг друга для будущих отчетов, но они могут дублироваться новыми пользователями, добавленными позже.

Что я пробовал

Я добавил поле is_not_duplicate в пользовательскую таблицу, но затем, если новый дубликат "Крис Бейкер" будет добавлен в базу данных, это приведет к тому, что эта ситуация не будет отображаться в дублирующем отчете; is_not_duplicate неправильно исключает один из аккаунтов. Мое утверждение HAVING не будет соответствовать порогу > 1 до тех пор, пока не появятся два дубликата Криса Бейкера, плюс "настоящий", помеченный is_not_duplicate.

Подытоженный вопрос

Как я могу встроить исключения в вышеупомянутый запрос без зацикливания результатов или нескольких запросов?

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

Ответы [ 16 ]

0 голосов
/ 24 августа 2012

На вашем месте я добавлю несколько таблиц / полей геолокации в схему базы данных.

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

Удачи.

0 голосов
/ 24 августа 2012

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

например, в этом примере у нас будет

id 1 | id 2

 2      4

, если crayzyguy@crazy.com и chris@gmail.com разные люди.

0 голосов
/ 24 августа 2012

Есть ли веская причина для того, чтобы не объединять дублирующиеся учетные записи в одну учетную запись?

Из комментариев кажется, что информация используется в основном для контактной информации, поэтому объединение должно быть относительно безболезненным и с низким риском.После объединения пользователей они больше не будут отображаться в вашем дубликате отчета.Кроме того, таблица ваших пользователей фактически уменьшится, что может повысить производительность.

0 голосов
/ 23 августа 2012

Если вы согласны внести небольшие изменения в формат отчета. Вы можете сделать самостоятельное соединение, как это -

SELECT 
    CONCAT(u1.id,",", u2.id) AS "ids",
    CONCAT(UPPER(u1.first_name), UPPER(u1.last_name)) AS "name"
FROM 
    users u1, users u2
WHERE
    u1.id < u2.id AND
    UPPER(u1.first_name) = UPPER(u2.first_name) AND
    UPPER(u1.last_name) = UPPER(u2.last_name) AND
    CONCAT(u1.id,",", u2.id) NOT IN (SELECT ids from not_dupe)

, который сообщает дубликаты следующим образом:

ids | name
----|--------
1,2 | CHRISBAKER
1,3 | CHRISBAKER
...

И таблица not_dupe будет иметь строки, подобные приведенным ниже:

ids
------
1,2
3,4
...
0 голосов
/ 21 августа 2012

Я не уверен, сработает ли это, но не могли бы вы рассмотреть обратную логику добавления столбца * is_duplicate_of *? Таким образом, вы можете пометить дубликаты, введя идентификатор первой записи в этом столбце, который будет больше нуля. Записи, которые вы хотите сохранить, будут иметь значение 0 в этом поле. Вы можете установить значение по умолчанию (непроверенные записи) равным -1, чтобы отслеживать состояние проверки для каждой записи.

После этого вы можете продолжить выполнение SQL, который будет сравнивать только новые записи с правильными записями, имеющими is_duplicate_of = 0 .

0 голосов
/ 03 марта 2012

Я бы пошел дальше и сделал бы столбец "Verified_unique", по умолчанию "False".

Чтобы избежать упомянутых вами проблем,

Тогда я бы выбрал все элементы, которые могут выглядеть как дубликаты, и имел бы «False» запись для «Verified_unique».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...