Какой лучший способ дедупликации таблицы? - PullRequest
29 голосов
/ 09 февраля 2010

Я видел несколько решений для этого, но мне интересно, какой лучший и самый эффективный способ состоит в том, чтобы де-дупле стол. Вы можете использовать код (SQL и т. Д.), Чтобы проиллюстрировать свою точку зрения, но я просто ищу базовые алгоритмы. Я предполагал, что уже будет вопрос об этом на SO, но я не смог найти его, поэтому, если он уже существует, просто дайте мне знать.

(Просто чтобы уточнить - я имею в виду избавление от дубликатов в таблице, в которой имеется пошаговое автоматическое PK и есть строки, которые являются дубликатами во всем, кроме поля PK.)

Ответы [ 15 ]

0 голосов
/ 12 ноября 2014

Вот один, с которым я столкнулся в реальной жизни.

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

    ;WITH Logins AS
    (
        SELECT [LoginId],[UserId],[Provider],[ProviderKey]
        FROM [dbo].[UserLogin] 
        WHERE [UserId]=@FromUserID -- is the user we're deleting
              OR [UserId]=@ToUserID -- is the user we're moving data to
    ), Ranked AS 
    (
        SELECT Logins.*
            , [Picker]=ROW_NUMBER() OVER (
                       PARTITION BY [Provider],[ProviderKey]
                       ORDER BY CASE WHEN [UserId]=@FromUserID THEN 1 ELSE 0 END)
        FROM Logins
    )
    MERGE Logins AS T
    USING Ranked AS S
    ON S.[LoginId]=T.[LoginID]
    WHEN MATCHED AND S.[Picker]>1 -- duplicate Provider/ProviderKey
                 AND T.[UserID]=@FromUserID -- safety check 
    THEN DELETE
    WHEN MATCHED AND S.[Picker]=1 -- the only or best one
                 AND T.[UserID]=@FromUserID
    THEN UPDATE SET T.[UserID]=@ToUserID
    OUTPUT $action, DELETED.*, INSERTED.*;
0 голосов
/ 17 июля 2014

Это может дедуплицировать дублированные значения в c1:

select * from foo
minus
select f1.* from foo f1, foo f2
where f1.c1 = f2.c1 and f1.c2 > f2.c2
0 голосов
/ 09 февраля 2010

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

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

0 голосов
/ 09 февраля 2010

Для SQL вы можете использовать таблицу INSERT IGNORE INTO SELECT xy FROM unkeyed_table;

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

0 голосов
/ 09 февраля 2010

Вы можете сгенерировать хеш для каждой строки (исключая PK), сохранить его в новом столбце (или, если вы не можете добавить новые столбцы, можете ли вы переместить таблицу во временную область подготовки?), А затем посмотреть для всех остальных строк с таким же хешем. Конечно, вы должны быть в состоянии гарантировать, что ваша хеш-функция не выдает одинаковый код для разных строк.

Если две строки повторяются, имеет ли значение, от чего вы избавляетесь? Возможно ли, что другие данные зависят от обоих дубликатов? Если это так, вам придется пройти несколько шагов:

  • Найди дуплей
  • Выберите один из них как dupeA, чтобы исключить
  • Найти все данные, зависящие от dupeA
  • Измените эти данные, чтобы они ссылались на dupeB
  • удалить dupeA.

Это может быть легко или сложно, в зависимости от существующей модели данных.

Весь этот сценарий звучит как проект по техническому обслуживанию и перепроектированию. Если так, то удачи !!

...