Как я могу удалить дубликаты строк?

Каков наилучший способ удалить дублирующиеся строки из довольно большой таблицы SQL Server (т.е. е. 300 000+ строк)

Строки, конечно, не будут идеальными дубликатами из-за существования поля идентификатора RowID.

MyTable

RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null
вопрос задан 20.08.2008
Seibar
34266 репутация

36 ответов


  • 0 рейтинг

    Вот еще одна хорошая статья о , удаляющая дубликаты .

    Здесь обсуждается, почему его сложно: « SQL основан на реляционной алгебре, и дубликаты не могут встречаться в реляционной алгебре, потому что дубликаты не допускаются в наборе. "

    Решение временной таблицы и два примера mysql.

    В будущем вы собираетесь предотвратить это на уровне базы данных или с точки зрения приложения. Я бы предложил уровень базы данных, потому что ваша база данных должна отвечать за поддержание ссылочной целостности, разработчики просто вызовут проблемы;)

    ответ дан Craig, с репутацией 1291, 20.08.2008
  • 0 рейтинг

    Если не принимать значения NULL, вы GROUP BY уникальных столбцов и SELECT RowId MIN (or MAX) в качестве строки для сохранения. Затем просто удалите все, что не имеет идентификатора строки:

    DELETE FROM MyTable
    LEFT OUTER JOIN (
       SELECT MIN(RowId) as RowId, Col1, Col2, Col3 
       FROM MyTable 
       GROUP BY Col1, Col2, Col3
    ) as KeepRows ON
       MyTable.RowId = KeepRows.RowId
    WHERE
       KeepRows.RowId IS NULL
    

    В случае, если у вас есть GUID вместо целого числа, вы можете заменить

    MIN(RowId)
    

    с

    CONVERT(uniqueidentifier, MIN(CONVERT(char(36), MyGuidColumn)))
    
    ответ дан Mark Brackett, с репутацией 74179, 20.08.2008
  • 0 рейтинг

    Извлечь повторяющиеся строки:

    SELECT
    name, email, COUNT(*)
    FROM 
    users
    GROUP BY
    name, email
    HAVING COUNT(*) > 1
    

    Удалить повторяющиеся строки:

    DELETE users 
    WHERE rowid NOT IN 
    SELECT MIN(rowid)
    FROM users
    GROUP BY name, email);
    
    ответ дан Shaini Sinha, с репутацией 234, 29.12.2016
  • 0 рейтинг
    1. Создать новую пустую таблицу с такой же структурой

    2. Выполнить запрос, как это

      INSERT INTO tc_category1
      SELECT *
      FROM tc_category
      GROUP BY category_id, application_id
      HAVING count(*) > 1
      
    3. Затем выполните этот запрос

      INSERT INTO tc_category1
      SELECT *
      FROM tc_category
      GROUP BY category_id, application_id
      HAVING count(*) = 1
      
    ответ дан DrPizza, с репутацией 14569, 8.05.2009
  • 0 рейтинг
    CREATE TABLE car(Id int identity(1,1), PersonId int, CarId int)
    
    INSERT INTO car(PersonId,CarId)
    VALUES(1,2),(1,3),(1,2),(2,4)
    
    --SELECT * FROM car
    
    ;WITH CTE as(
    SELECT ROW_NUMBER() over (PARTITION BY personid,carid order by personid,carid) as rn,Id,PersonID,CarId from car)
    
    DELETE FROM car where Id in(SELECT Id FROM CTE WHERE rn>1)
    
    ответ дан AnandPhadke, с репутацией 10189, 11.07.2012
  • 0 рейтинг

    Теперь давайте посмотрим таблицу elasticalsearch, в которой в этих таблицах есть дублирующиеся строки, а Id - это идентичное поле uniq. Мы знаем, если какой-то идентификатор существует по групповым критериям, тогда мы можем удалить другие строки вне этой группы. Моя манера показывает этот критерий.

    Так много случаев этой темы находятся в моем подобном состоянии. Просто измените критерии целевой группы в соответствии с вашим случаем удаления повторяющихся (дублированных) строк.

    DELETE 
    FROM elasticalsearch
    WHERE Id NOT IN 
                   (SELECT min(Id)
                         FROM elasticalsearch
                         GROUP BY FirmId,FilterSearchString
                         ) 
    

    ура

    ответ дан dewelloper, с репутацией 94, 11.01.2016
  • 0 рейтинг

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

    UPDATE MY_TABLE
       SET DELETED = getDate()
     WHERE TABLE_ID IN (
        SELECT x.TABLE_ID
          FROM MY_TABLE x
          JOIN (SELECT min(TABLE_ID) id, COL_1, COL_2, COL_3
                  FROM MY_TABLE d
                 GROUP BY d.COL_1, d.COL_2, d.COL_3
                HAVING count(*) > 1) AS d ON d.COL_1 = x.COL_1
                                         AND d.COL_2 = x.COL_2
                                         AND d.COL_3 = x.COL_3
                                         AND d.TABLE_ID <> x.TABLE_ID
                 /*WHERE x.COL_4 <> 'D' -- Additional filter*/)
    

    Этот метод хорошо мне подошел для довольно умеренных таблиц, содержащих ~ 30 миллионов строк с большим и низким количеством дубликатов.

    ответ дан Brett Ryan, с репутацией 13694, 7.06.2016
  • 0 рейтинг

    Используйте это

    WITH tblTemp as
    (
    SELECT ROW_NUMBER() Over(PARTITION BY Name,Department ORDER BY Name)
       As RowNumber,* FROM 
    )
    DELETE FROM tblTemp where RowNumber >1
    
    ответ дан Haris, с репутацией 3167, 23.07.2015
  • 0 рейтинг

    О, конечно. Используйте временную таблицу. Если вы хотите «не очень производительное» утверждение, которое «работает», вы можете использовать:

    DELETE FROM MyTable WHERE NOT RowID IN
        (SELECT 
            (SELECT TOP 1 RowID FROM MyTable mt2 
            WHERE mt2.Col1 = mt.Col1 
            AND mt2.Col2 = mt.Col2 
            AND mt2.Col3 = mt.Col3) 
        FROM MyTable mt)
    

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

    ответ дан Jacob Proffitt, с репутацией 11006, 20.08.2008
  • 0 рейтинг

    С помощью запроса ниже мы можем удалить дубликаты записей на основе одного или нескольких столбцов. ниже запрос удаляется на основе двух столбцов. имя таблицы: testing и имена столбцов empno,empname

    DELETE FROM testing WHERE empno not IN (SELECT empno FROM (SELECT empno, ROW_NUMBER() OVER (PARTITION BY empno ORDER BY empno) 
    AS [ItemNumber] FROM testing) a WHERE ItemNumber > 1)
    or empname not in
    (select empname from (select empname,row_number() over(PARTITION BY empno ORDER BY empno) 
    AS [ItemNumber] FROM testing) a WHERE ItemNumber > 1)
    
    ответ дан Sudhakar NV, с репутацией 91, 8.02.2012
  • 0 рейтинг
    alter table MyTable add sno int identity(1,1)
        delete from MyTable where sno in
        (
        select sno from (
        select *,
        RANK() OVER ( PARTITION BY RowID,Col3 ORDER BY sno DESC )rank
        From MyTable
        )T
        where rank>1
        )
    
        alter table MyTable 
        drop  column sno
    
    ответ дан Chanukya, с репутацией 4330, 16.12.2015
  • 0 рейтинг

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

    Вот соответствующие части со связанной страницы:

    Рассмотрим эти данные:

    EMPLOYEE_ID ATTENDANCE_DATE
    A001    2011-01-01
    A001    2011-01-01
    A002    2011-01-01
    A002    2011-01-01
    A002    2011-01-01
    A003    2011-01-01
    

    Итак, как мы можем удалить эти дубликаты данных?

    Сначала вставьте столбец идентификаторов в эту таблицу, используя следующий код:

    ALTER TABLE dbo.ATTENDANCE ADD AUTOID INT IDENTITY(1,1)  
    

    Используйте следующий код для его решения:

    DELETE FROM dbo.ATTENDANCE WHERE AUTOID NOT IN (SELECT MIN(AUTOID) _
        FROM dbo.ATTENDANCE GROUP BY EMPLOYEE_ID,ATTENDANCE_DATE) 
    
    ответ дан Nitish Pareek, с репутацией 1103, 6.08.2013
  • 0 рейтинг

    Это удалит дубликаты строк, кроме первой строки

    DELETE
    FROM
        Mytable
    WHERE
        RowID NOT IN (
            SELECT
                MIN(RowID)
            FROM
                Mytable
            GROUP BY
                Col1,
                Col2,
                Col3
        )
    

    См. ( http: // www. CodeProject. ru / Articles / 157977 / Remove-Duplicate-Rows-from-a-Table-in-SQL-Server )

    ответ дан Syed Mohamed, с репутацией 1025, 10.09.2013
  • 0 рейтинг

    Это самый простой способ удалить повторяющуюся запись

     DELETE FROM tblemp WHERE id IN 
     (
      SELECT MIN(id) FROM tblemp
       GROUP BY  title HAVING COUNT(id)>1
     )
    

    http: // askme. indianyouth. info / details / how-to-dumplicate-запись-из-таблицы-в-использовании-sql-105

    ответ дан Harikesh Yadav, с репутацией 127, 28.09.2016
  • 0 рейтинг

    Я думаю, что это было бы полезно. Здесь ROW_NUMBER () OVER (PARTITION BY res1. Название ЗАКАЗАТЬ ПО РЕЗ1. Id), поскольку номер использовался для различения дублирующихся строк.

    delete FROM
    (SELECT res1.*,ROW_NUMBER() OVER(PARTITION BY res1.Title ORDER BY res1.Id)as num
     FROM 
    (select * from [dbo].[tbl_countries])as res1
    )as res2
    WHERE res2.num > 1
    
    ответ дан Selim Reza, с репутацией 603, 10.06.2018
  • 0 рейтинг

    Быстрое и грязное удаление точных дублированных строк (для небольших таблиц):

    select  distinct * into t2 from t1;
    delete from t1;
    insert into t1 select *  from t2;
    drop table t2;
    
    ответ дан JuanJo, с репутацией 235, 5.02.2013
  • 0 рейтинг

    Следующий запрос полезен для удаления дублирующихся строк. Таблица в этом примере имеет ID в качестве столбца идентификаторов, а столбцы с дублирующимися данными - Column1, Column2 и Column3.

    DELETE FROM TableName
    WHERE  ID NOT IN (SELECT MAX(ID)
                      FROM   TableName
                      GROUP  BY Column1,
                                Column2,
                                Column3
                      /*Even if ID is not null-able SQL Server treats MAX(ID) as potentially
                        nullable. Because of semantics of NOT IN (NULL) including the clause
                        below can simplify the plan*/
                      HAVING MAX(ID) IS NOT NULL) 
    

    Следующий скрипт показывает использование GROUP BY, HAVING, ORDER BY в одном запросе и возвращает результаты с повторяющимся столбцом и его количеством.

    SELECT YourColumnName,
           COUNT(*) TotalCount
    FROM   YourTableName
    GROUP  BY YourColumnName
    HAVING COUNT(*) > 1
    ORDER  BY COUNT(*) DESC 
    
    ответ дан gngolakia, с репутацией 1795, 23.11.2011
  • 0 рейтинг

    С уровня приложения (к сожалению). Я согласен с тем, что правильный способ предотвращения дублирования на уровне базы данных - использование уникального индекса, но в SQL Server 2005 индекс может быть только 900 байтов, и мое поле varchar (2048) сметает это.

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

    -- given a table stories(story_id int not null primary key, story varchar(max) not null)
    CREATE TRIGGER prevent_plagiarism 
    ON stories 
    after INSERT, UPDATE 
    AS 
        DECLARE @cnt AS INT 
    
        SELECT @cnt = Count(*) 
        FROM   stories 
               INNER JOIN inserted 
                       ON ( stories.story = inserted.story 
                            AND stories.story_id != inserted.story_id ) 
    
        IF @cnt > 0 
          BEGIN 
              RAISERROR('plagiarism detected',16,1) 
    
              ROLLBACK TRANSACTION 
          END 
    

    Кроме того, varchar (2048) звучит для меня подозрительно (некоторые вещи в жизни имеют размер 2048 байт, но это довольно редко); разве это не должно быть varchar (max)?

    ответ дан DrPizza, с репутацией 14569, 20.08.2008
  • 0 рейтинг
    delete t1
    from table t1, table t2
    where t1.columnA = t2.columnA
    and t1.rowid>t2.rowid
    

    Postgres:

    delete
    from table t1
    using table t2
    where t1.columnA = t2.columnA
    and t1.rowid > t2.rowid
    
    ответ дан SoftwareGeek, с репутацией 6381, 30.09.2010
  • 0 рейтинг
    DELETE 
    FROM MyTable
    WHERE NOT EXISTS (
                  SELECT min(RowID)
                  FROM Mytable
                  WHERE (SELECT RowID 
                         FROM Mytable
                         GROUP BY Col1, Col2, Col3
                         ))
                   );
    
    ответ дан Jayron Soares, с репутацией 205, 2.01.2014
  • 0 рейтинг

    Я бы предпочел CTE для удаления повторяющихся строк из таблицы сервера SQL

    настоятельно рекомендуем следовать этой статье :: http: // codaffection. com / sql-server-article / delete-duplicate-row-in-sql-server /

    , сохранив оригинал

    WITH CTE AS
    (
    SELECT *,ROW_NUMBER() OVER (PARTITION BY col1,col2,col3 ORDER BY col1,col2,col3) AS RN
    FROM MyTable
    )
    
    DELETE FROM CTE WHERE RN<>1
    

    без сохранения оригинала

    WITH CTE AS
    (SELECT *,R=RANK() OVER (ORDER BY col1,col2,col3)
    FROM MyTable)
    
    DELETE CTE
    WHERE R IN (SELECT R FROM CTE GROUP BY R HAVING COUNT(*)>1)
    
    ответ дан Shamseer K, с репутацией 2221, 19.05.2015
  • 0 рейтинг

    Если вы хотите просмотреть строки, которые вы собираетесь удалить, и сохранить контроль над тем, какие из повторяющихся строк оставить. См. http: // developer. azurewebsites. net / 2014/09 / лучше-sql-group-by-find-duplicate-data /

    with MYCTE as (
      SELECT ROW_NUMBER() OVER (
        PARTITION BY DuplicateKey1
                    ,DuplicateKey2 -- optional
        ORDER BY CreatedAt -- the first row among duplicates will be kept, other rows will be removed
      ) RN
      FROM MyTable
    )
    DELETE FROM MYCTE
    WHERE RN > 1
    
    ответ дан Lauri Lubi, с репутацией 450, 1.01.2015
  • 0 рейтинг

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

    begin transaction
    -- create temp table with identical structure as source table
    Select * Into #temp From tableName Where 1 = 2
    
    -- insert distinct values into temp
    insert into #temp 
    select distinct * 
    from  tableName
    
    -- delete from source
    delete from tableName 
    
    -- insert into source from temp
    insert into tableName 
    select * 
    from #temp
    
    rollback transaction
    -- if this works, change rollback to commit and execute again to keep you changes!!
    

    PS: при работе над такими вещами я всегда использую транзакцию, это не только гарантирует, что все выполняется в целом, но и позволяет мне тестировать, не рискуя ничем. Но, конечно, вы должны сделать резервную копию в любом случае, просто чтобы быть уверенным. , ,

    ответ дан Ruben Verschueren, с репутацией 688, 27.01.2014
  • 0 рейтинг
    SELECT  DISTINCT *
          INTO tempdb.dbo.tmpTable
    FROM myTable
    
    TRUNCATE TABLE myTable
    INSERT INTO myTable SELECT * FROM tempdb.dbo.tmpTable
    DROP TABLE tempdb.dbo.tmpTable
    
    ответ дан heta77, с репутацией 159, 10.10.2012
  • 0 рейтинг

    Я предпочитаю подзапрос \ имеющий count (*) & gt; 1 решение внутреннего соединения, потому что мне было легче читать, и было очень легко превратиться в оператор SELECT, чтобы проверить, что будет удалено, прежде чем вы запустите его.

    --DELETE FROM table1 
    --WHERE id IN ( 
         SELECT MIN(id) FROM table1 
         GROUP BY col1, col2, col3 
         -- could add a WHERE clause here to further filter
         HAVING count(*) > 1
    --)
    
    ответ дан James Errico, с репутацией 1971, 1.03.2014
  • 0 рейтинг

    Я хотел бы упомянуть этот подход, а также он может быть полезным и работает на всех серверах SQL: Довольно часто есть только один - два дубликата, и идентификаторы и количество дубликатов известны. В этом случае:

    SET ROWCOUNT 1 -- or set to number of rows to be deleted
    delete from myTable where RowId = DuplicatedID
    SET ROWCOUNT 0
    
    ответ дан Evgueny Sedov, с репутацией 119, 30.01.2013
  • 0 рейтинг

    У меня была таблица, где мне нужно было сохранить неповторяющиеся строки. Я не уверен в скорости или эффективности.

    DELETE FROM myTable WHERE RowID IN (
      SELECT MIN(RowID) AS IDNo FROM myTable
      GROUP BY Col1, Col2, Col3
      HAVING COUNT(*) = 2 )
    
    ответ дан chrismar035, с репутацией 728, 11.12.2009
  • 0 рейтинг

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

        CREATE PROCEDURE sp_DeleteDuplicate @tableName varchar(100), @DebugMode int =1
    AS 
    BEGIN
    SET NOCOUNT ON;
    
    IF(OBJECT_ID('tempdb..#tableMatrix') is not null) DROP TABLE #tableMatrix;
    
    SELECT ROW_NUMBER() OVER(ORDER BY name) as rn,name into #tableMatrix FROM sys.columns where [object_id] = object_id(@tableName) ORDER BY name
    
    DECLARE @MaxRow int = (SELECT MAX(rn) from #tableMatrix)
    IF(@MaxRow is null)
        RAISERROR  ('I wasn''t able to find any columns for this table!',16,1)
    ELSE 
        BEGIN
    DECLARE @i int =1 
    DECLARE @Columns Varchar(max) ='';
    
    WHILE (@i <= @MaxRow)
    BEGIN 
        SET @Columns=@Columns+(SELECT '['+name+'],' from #tableMatrix where rn = @i)
    
        SET @i = @i+1;
    END
    
    ---DELETE LAST comma
    SET @Columns = LEFT(@Columns,LEN(@Columns)-1)
    
    DECLARE @Sql nvarchar(max) = '
    WITH cteRowsToDelte
         AS (
    SELECT ROW_NUMBER() OVER (PARTITION BY '+@Columns+' ORDER BY ( SELECT 0)) as rowNumber,* FROM '+@tableName
    +')
    
    DELETE FROM cteRowsToDelte
    WHERE  rowNumber > 1;
    '
    SET NOCOUNT OFF;
        IF(@DebugMode = 1)
           SELECT @Sql
        ELSE
           EXEC sp_executesql @Sql
        END
    END
    

    Итак, если вы создадите таблицу, как это:

    IF(OBJECT_ID('MyLitleTable') is not null)
        DROP TABLE MyLitleTable 
    
    
    CREATE TABLE MyLitleTable
    (
        A Varchar(10),
        B money,
        C int
    )
    ---------------------------------------------------------
    
        INSERT INTO MyLitleTable VALUES
        ('ABC',100,1),
        ('ABC',100,1), -- only this row should be deleted
        ('ABC',101,1),
        ('ABC',100,2),
        ('ABCD',100,1)
    
        -----------------------------------------------------------
    
         exec sp_DeleteDuplicate 'MyLitleTable',0
    

    Он удалит все дубликаты из вашей таблицы. Если вы запустите его без второго параметра, он вернет оператор SQL для запуска.

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

    ответ дан Jakub Ojmucianski, с репутацией 116, 13.04.2017
  • 0 рейтинг
    DELETE
    FROM
        table_name T1
    WHERE
        rowid > (
            SELECT
                min(rowid)
            FROM
                table_name T2
            WHERE
                T1.column_name = T2.column_name
        );
    
    ответ дан Teena, с репутацией 71, 3.10.2013
  • 0 рейтинг

    Другой способ - . Создайте новую таблицу с теми же полями и с уникальным индексом . Затем переместить все данные из старой таблицы в новую таблицу . Автоматически SQL SERVER игнорирует (есть также вариант, что делать, если будет повторяющееся значение: игнорировать, прерывать или sth) повторяющихся значений. Итак, у нас одна и та же таблица без повторяющихся строк. Если вы не хотите иметь уникальный индекс, после передачи данных вы можете удалить его .

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

    ответ дан İsmail Yavuz, с репутацией 2469, 18.09.2013
  • 0 рейтинг
    DELETE LU 
    FROM   (SELECT *, 
                   Row_number() 
                     OVER ( 
                       partition BY col1, col1, col3 
                       ORDER BY rowid DESC) [Row] 
            FROM   mytable) LU 
    WHERE  [row] > 1 
    
    ответ дан Jithin Shaji, с репутацией 3855, 21.05.2014
  • 0 рейтинг

    Другой возможный способ сделать это -

    ; 
    
    --Ensure that any immediately preceding statement is terminated with a semicolon above
    WITH cte
         AS (SELECT ROW_NUMBER() OVER (PARTITION BY Col1, Col2, Col3 
                                           ORDER BY ( SELECT 0)) RN
             FROM   #MyTable)
    DELETE FROM cte
    WHERE  RN > 1;
    

    Я использую ORDER BY (SELECT 0) выше, так как это произвольно, какой ряд сохранить в случае связи.

    Чтобы сохранить последний в порядке RowID, например, вы можете использовать ORDER BY RowID DESC

    Планы выполнения

    План выполнения для этого часто проще и эффективнее, чем в принятом ответе, так как не требует самостоятельного соединения.

    Execution Plans

    Однако это не всегда так. Единственное место, где решение GROUP BY может быть предпочтительным, - это ситуации, в которых хеш-агрегат будет выбран предпочтительнее агрегата потока.

    Решение ROW_NUMBER всегда дает один и тот же план, тогда как стратегия GROUP BY является более гибкой.

    Execution Plans

    Факторы, которые могли бы способствовать подходу агрегирования хэшей, были бы

    • Нет полезного индекса для столбцов разделения
    • относительно меньше групп с относительно большим количеством дубликатов в каждой группе

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

    ответ дан Martin Smith, с репутацией 333672, 29.09.2010
  • 0 рейтинг

    На сайте поддержки Microsoft есть хорошая статья о удалении дубликатов . Это довольно консервативно - они заставляют вас делать все в отдельных шагах - но это должно хорошо работать с большими столами.

    В прошлом я использовал для этого самостоятельные объединения, хотя, возможно, это можно было сделать с помощью предложения HAVING:

    DELETE dupes
    FROM MyTable dupes, MyTable fullTable
    WHERE dupes.dupField = fullTable.dupField 
    AND dupes.secondDupField = fullTable.secondDupField 
    AND dupes.uniqueField > fullTable.uniqueField
    
    ответ дан Jon Galloway, с репутацией 39262, 20.08.2008
  • 0 рейтинг

    Использование CTE. Идея состоит в том, чтобы объединить один или несколько столбцов, которые образуют дублирующуюся запись, а затем удалить то, что вам больше нравится:

    ;with cte as (
        select 
            min(PrimaryKey) as PrimaryKey
            UniqueColumn1,
            UniqueColumn2
        from dbo.DuplicatesTable 
        group by
            UniqueColumn1, UniqueColumn1
        having count(*) > 1
    )
    delete d
    from dbo.DuplicatesTable d 
    inner join cte on 
        d.PrimaryKey > cte.PrimaryKey and
        d.UniqueColumn1 = cte.UniqueColumn1 and 
        d.UniqueColumn2 = cte.UniqueColumn2;
    
    ответ дан ostati, с репутацией 2408, 13.11.2014
  • 0 рейтинг

    Другой способ сделать это: -

    DELETE A
    FROM   TABLE A,
           TABLE B
    WHERE  A.COL1 = B.COL1
           AND A.COL2 = B.COL2
           AND A.UNIQUEFIELD > B.UNIQUEFIELD 
    
    ответ дан yuvi, с репутацией 503, 2.02.2016
  • 0 рейтинг

    Этот запрос показал очень хорошую производительность для меня:

    DELETE tbl
    FROM
        MyTable tbl
    WHERE
        EXISTS (
            SELECT
                *
            FROM
                MyTable tbl2
            WHERE
                tbl2.SameValue = tbl.SameValue
            AND tbl.IdUniqueValue < tbl2.IdUniqueValue
        )
    

    он удалил 1M строк за чуть более 30 секунд из таблицы 2M (50% дубликатов)

    ответ дан Draško, с репутацией 414, 10.12.2014