Проверка на наличие дубликатов данных в SQL Server - PullRequest
4 голосов
/ 02 июня 2011

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

Например

alex, 1
alex, 1
liza, 32
hary, 34

Мне нужно исключить из этой таблицы одноиз alex, 1 строк

Я знаю, что этот алгоритм будет очень неэффективным, но это не имеет значения.Мне нужно будет удалить дубликаты данных.

Каков наилучший способ сделать это?Пожалуйста, имейте в виду, что у меня нет 2 полей, на самом деле у меня есть около 10 полей для проверки.

Ответы [ 5 ]

6 голосов
/ 02 июня 2011

Как вы сказали, да, это будет очень неэффективно, но вы можете попробовать что-то вроде

DECLARE @TestTable TABLE(
        Name VARCHAR(20),
        SomeVal INT
)
INSERT INTO @TestTable SELECT 'alex', 1
INSERT INTO @TestTable SELECT 'alex', 1
INSERT INTO @TestTable SELECT 'liza', 32
INSERT INTO @TestTable SELECT 'hary', 34

SELECT  *
FROM    @TestTable

;WITH DuplicateVals AS (
    SELECT  *,
            ROW_NUMBER() OVER (PARTITION BY Name, SomeVal ORDER BY (SELECT NULL)) RowID
    FROM    @TestTable
)
DELETE FROM DuplicateVals WHERE RowID > 1

SELECT *
FROM    @TestTable
3 голосов
/ 02 июня 2011

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

Быстрое решение , если вы не возражаете против создания новой таблицы, создайте новую таблицу с той же схемой с именем NewTable.

Выполнить этот SQL

 Insert into NewTable
 Select 
   name, 
   num 
 from
   OldTable
 group by
   name,
   num

Просто включите каждое имя поля как в операторы select, так и group by.

2 голосов
/ 02 июня 2011

Немного другое решение, для которого требуется первичный ключ (или уникальный индекс): Предположим, у вас есть стол your_table(id - PK, name, and num)

DELETE 
FROM your_table     
FROM your_table AS t2
WHERE 
(select  COUNT(*) FROM your_table y 
  where t2.name = y.name and  t2.num = y.num) >1
AND t2.id != 
(SELECT top 1 id FROM your_table z 
 WHERE t2.name = z.name and  t2.num = z.num);

Я предположил, что name и num NOT NULL, если они могут содержать NULL значений, вам нужно изменить where s в подзапросах.

2 голосов
/ 02 июня 2011

Метод А. Вы можете получить дедуплицированную версию ваших данных, используя

SELECT field1, field2, ...
INTO Deduped
FROM Source
GROUP BY field1, field2, ...

например, для ваших данных выборки,

SELECT name, number
FROM Source
GROUP BY name, number

выходы

alex    1
hary    34
liza    32

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

Метод B. Метод на месте - создать первичный ключ и таким образом удалить дубликаты. Например, вы можете

ALTER TABLE Source ADD sid INT IDENTITY(1,1);

, что делает Source похожим на это

alex    1   1
alex    1   2
liza    32  3
hary    34  4

тогда вы можете использовать

DELETE FROM Source
WHERE  sid NOT IN
  (SELECT MIN(sid)
   FROM  Source
   GROUP BY name, number)

, который даст желаемый результат. Конечно, «НЕ В» не совсем самый эффективный, но он сделает свою работу. В качестве альтернативы, вы можете ВЕРНУТЬСЯ В Сгруппированную таблицу (может быть, хранится в таблице TEMP) и выполнить УДАЛИТЬ таким образом.

2 голосов
/ 02 июня 2011
create table DuplicateTable(name varchar(10), number int)

insert DuplicateTable
values
    ('alex', 1),
    ('alex', 1),
    ('liza', 32),
    ('hary', 34);

with cte
as
(
    select *, row_number() over(partition by name, number order by name) RowNumber
    from DuplicateTable
)
delete cte
where RowNumber > 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...