Как удалить дубликаты строк в SQL Server 2008? - PullRequest
3 голосов
/ 31 октября 2009

Как я могу удалить повторяющиеся строки в SQL Server 2008?

Ответы [ 4 ]

11 голосов
/ 24 августа 2011

Самый простой способ - использовать CTE (общее табличное выражение). Я использую этот метод, когда у меня есть необработанные данные для импорта; первое, что я делаю, чтобы очистить его, чтобы убедиться, что нет дубликатов - у меня есть какой-то уникальный дескриптор для каждой строки.

Резюме:

WITH numbered AS (
    SELECT ROW_NUMBER() OVER(PARTITION BY [dupe-column-list] ORDER BY [dupe-column-list]) AS _dupe_num FROM [table-name] WHERE 1=1
)
DELETE FROM numbered WHERE _dupe_num > 1;

В части "dupe-column-list" вы перечисляете все задействованные столбцы, где вы хотите, чтобы значения были уникальными. ORDER BY - это место, где вы решаете, в пределах набора дубликатов, какая строка «выигрывает», а какая удаляется. («ГДЕ 1 = 1» - это просто личная привычка.)

Причина, по которой это работает, заключается в том, что Sql Server хранит внутреннюю уникальную ссылку на каждую строку источника, выбранную в CTE. Таким образом, когда DELETE выполняется, он знает точную строку, которую нужно удалить, независимо от того, что вы поместили в список выбора вашего CTE. (Если вы нервничаете, вы можете изменить «УДАЛИТЬ» на «ВЫБОР *», но поскольку у вас есть дублирующиеся строки, это не поможет; если бы вы могли однозначно идентифицировать каждую строку, вы бы не читали это .)

Пример:

CREATE TABLE ##_dupes (col1 int, col2 int, col3 varchar(50));
INSERT INTO ##_dupes 
    VALUES (1, 1, 'one,one')
        , (2, 2, 'two,two')
        , (3, 3, 'three,three')
        , (1, 1, 'one,one')
        , (1, 2, 'one,two')
        , (3, 3, 'three,three')
        , (1, 1, 'one,one')
        , (1, 2, '1,2');

Из 8 рядов у вас есть 5, связанных с дублирующимися проблемами; 3 ряда должны быть удалены. Вы можете увидеть проблемы с этим:

SELECT col1
    , col2
    , col3
    , COUNT(1) AS _total 
    FROM ##_dupes 
    WHERE 1=1 
    GROUP BY col1, col2, col3
    HAVING COUNT(1) > 1
    ORDER BY _total DESC;

Теперь выполните следующий запрос, чтобы удалить дубликаты, оставив по 1 строке из каждого набора дубликатов.

WITH numbered AS (
    SELECT ROW_NUMBER() OVER(PARTITION BY col1, col2, col3 ORDER BY col1, col2, col3) AS _dupe_num FROM ##_dupes WHERE 1=1
)
DELETE FROM numbered WHERE _dupe_num > 1;

Теперь у вас осталось 5 строк, ни один из которых не продублирован.

4 голосов
/ 01 ноября 2009

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

Представьте, что у вас есть стол вроде:

create table T (
    id int identity,
    colA varchar(30) not null,
    colB varchar(30) not null
)

Тогда вы можете сказать что-то вроде:

delete T
from T t1
where exists
(select null from T t2
where t2.colA = t1.colA
and t2.colB = t1.colB
and t2.id <> t1.id)

Еще одна хитрость - выбрать отдельные записи с минимальным идентификатором и сохранить их:

delete T
where id not in
(select min(id) from T
group by colA, colB)

(Извините, я не проверял их, но одна из этих идей может привести вас к вашему решению.)

Обратите внимание, что если у вас нет первичного ключа, единственный другой способ сделать это - использовать псевдостолбец, такой как ROWID - но я не уверен, предлагает ли SQL Server 2008 эту идею.

3 голосов
/ 13 февраля 2013

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

delete from (Tablename)
          where tablename.%%physloc%%
          NOT IN (select MIN(b.%%physloc%%)
          from tablename b
          group by b.Column1,b.column2,b.column3
          );
0 голосов
/ 31 октября 2009

Предполагая, что у вас есть первичный ключ с именем id, а другие столбцы - col2 ... coln, и что под "дублирующимися" строками вы подразумеваете все строки, в которых дублируются все значения столбцов, кроме PK

delete from A where id not in
(select min(id) from A
group by col2, col3, ...coln) as x

т.е. группа по всем столбцам без PK

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