2010-02-09 2 views
25

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

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

+0

Вы имеете в виду коллапсирующие * идентичные * дубликаты (кроме ПК) или свертывающие * достаточно похожие * дубликаты? Первое можно сделать довольно прямо, последний - потенциальный мир неопределенности и боли. –

+0

@j_random_hacker - Я имел в виду совершенно идентичный. См. Формулировку сообщения: «Я имею в виду избавление от дубликатов ... строк, которые дублируются в * все, кроме поля ПК *». – froadie

+0

Извините, я не читал достаточно внимательно ... –

ответ

1

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

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

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

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

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

+0

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

+0

@EsbenP: Я видел заархивированные строки, используемые как своего рода хеш для исходных строк. По крайней мере, вы не обманываете. – FrustratedWithFormsDesigner

+0

Я предполагал, что никакие другие данные не зависят от поля ПК. Но это интересный момент: что бы вы сделали, если бы это было так? Это сделало бы его намного сложнее ... Любые идеи? – froadie

0

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

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

0

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

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

7

SELECT DISTINCT <insert all columns but the PK here> FROM foo. Создайте временную таблицу с использованием этого запроса (синтаксис зависит от РСУБД, но, как правило, имеется шаблон SELECT … INTO или CREATE TABLE AS), затем сдуйте старую таблицу и перекачивайте данные из таблицы темпа обратно в нее.

8

Deduping редко бывает простым. Это потому, что учетные записи, которые должны быть дедуплированы, часто имеют несколько разные значения, это некоторые из полей. Поэтому выберите, какая запись сохранить может быть проблематичной. Кроме того, обманщики часто являются людьми, и трудно определить, являются ли два Джона Смита двумя людьми или одним человеком, который дублируется. Так что потратьте много (50% или более всего проекта) вашего времени, определяя, что составляет дуп, и как справляться с различиями и дочерними записями.

Откуда вы знаете, что является правильным значением? Дальнейшая дедупликация требует, чтобы вы обрабатывали все дочерние записи, а не сироты. Что происходит, когда вы обнаруживаете, что, изменив идентификатор на дочерней записи, вы внезапно нарушаете один из уникальных индексов или ограничений - это произойдет в конечном итоге, и ваш процесс должен обработать его. Если вы выбрали глупо, чтобы применить все свои ограничения только для тщательного приложения, вы можете даже не знать, что ограничения нарушены. Когда у вас есть 10 000 записей для дедупликации, вы не будете проходить через приложение для дедуплирования по одному за раз. Если ограничение не находится в базе данных, удачи в сохранении целостности данных при дедуплировании.

Еще одно осложнение заключается в том, что дубликаты не всегда точно совпадают с именем или адресом. Например, salesrep по имени Джоан Мартин может быть дубликом репутации продавца Joan Martin-Jones, особенно если у них одинаковый адрес и адрес электронной почты. Или вы могли бы иметь Джона или Джонни в названии. Или тот же адрес улицы, кроме одной записи, аббревиатура ST. и одну простую улицу. В SQL-сервере вы можете использовать SSIS и нечеткую группировку, чтобы также идентифицировать ближние совпадения. Они часто являются наиболее распространенными обманами, поскольку тот факт, что не были точными совпадениями, - это то, почему они попали в дуплексы в первую очередь.

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

1

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

ALTER ИГНОРИРУЙТЕ TABLE TABLE_NAME ADD UNIQUE (column1, column2, column3)

Вы можете удалить уникальные индексные слова.

3

Вот метод я использую, если вы можете получить ваши критерии надуть в группу заявления и в таблице есть столбец ID идентификации для уникальности:

delete t 
from tablename t 
inner join 
(
    select date_time, min(id) as min_id 
    from tablename 
    group by date_time 
    having count(*) > 1 
) t2 on t.date_time = t2.date_time 
where t.id > t2.min_id 

В этом примере date_time является группировкой критериев, если у вас есть более одного столбца, обязательно присоединитесь ко всем из них.

+0

Мне нравится этот. Я просто попробовал, и он отлично работает для меня. –

+0

Фантастическое решение! Благодаря! –

1

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

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

DELETE t 
FROM @USER_OUTBOX_APPS t 
INNER JOIN 
(
    SELECT 
     app_id 
     ,max(processed_date) as max_processed_date 
    FROM @USER_OUTBOX_APPS 
    GROUP BY app_id 
    HAVING count(*) > 1 
) t2 on 
    t.app_id = t2.app_id 
WHERE 
    t.processed_date < t2.max_processed_date 
0

Это может DeDupe дублированных значений в c1:

select * from foo 
minus 
select f1.* from foo f1, foo f2 
where f1.c1 = f2.c1 and f1.c2 > f2.c2 
7

Использование аналитической функции row_number:

WITH CTE (col1, col2, dupcnt) 
AS 
(
SELECT col1, col2, 
ROW_NUMBER() OVER (PARTITION BY col1, col2 ORDER BY col1) AS dupcnt 
FROM Youtable 
) 
DELETE 
FROM CTE 
WHERE dupcnt > 1 
GO                 
0

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

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

;WITH Logins AS 
    (
     SELECT [LoginId],[UserId],[Provider],[ProviderKey] 
     FROM [dbo].[UserLogin] 
     WHERE [UserId][email protected] -- is the user we're deleting 
       OR [UserId][email protected] -- 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][email protected] 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][email protected] -- safety check 
    THEN DELETE 
    WHEN MATCHED AND S.[Picker]=1 -- the only or best one 
       AND T.[UserID][email protected] 
    THEN UPDATE SET T.[UserID][email protected] 
    OUTPUT $action, DELETED.*, INSERTED.*; 
5

Добавление фактического кода здесь для будущей ссылки

Итак, есть 3 шага, и, следовательно, 3 заявление SQL:

Шаг 1: Переместить НЕРАСПРОСТРАНЕНИЕ дубликатов (уникальные кортежи) в временный таблица

CREATE TABLE new_table as 
SELECT * FROM old_table WHERE 1 GROUP BY [column to remove duplicates by]; 

Шаг 2: удалить старую таблицу (или переименовать его) Мы больше не нужны таблицы со всеми дублирующих записей, так брось!

DROP TABLE old_table; 

Шаг 3: переименовать new_table к имени old_table

RENAME TABLE new_table TO old_table; 

И конечно, не забудьте исправить глючный код, чтобы остановить вставку дубликатов!

0

Эти методы будут работать, но без явного идентификатора в качестве ПК, а затем определение того, какие строки для удаления могут быть проблемой. Отказывание в таблице темпа удаление из оригинала и повторная установка без дубликатов, по-видимому, является самым простым.

 Смежные вопросы

  • Нет связанных вопросов^_^