Как я могу удалить дубликаты строк? - PullRequest
1221 голосов
/ 21 августа 2008

Каков наилучший способ удаления повторяющихся строк из довольно большой таблицы 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

Ответы [ 37 ]

10 голосов
/ 23 июля 2015

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

WITH tblTemp as
(
SELECT ROW_NUMBER() Over(PARTITION BY Name,Department ORDER BY Name)
   As RowNumber,* FROM <table_name>
)
DELETE FROM tblTemp where RowNumber >1
9 голосов
/ 08 февраля 2012

Используя приведенный ниже запрос, мы можем удалить дубликаты записей на основе одного или нескольких столбцов. ниже запрос удаляется на основе двух столбцов. Имя таблицы: 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)
9 голосов
/ 08 мая 2009
  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
    
9 голосов
/ 28 сентября 2016

Это самый простой способ удалить дубликат записи

 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-record-from-table-in-using-sql-105

7 голосов
/ 30 января 2013

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

SET ROWCOUNT 1 -- or set to number of rows to be deleted
delete from myTable where RowId = DuplicatedID
SET ROWCOUNT 0
7 голосов
/ 21 августа 2008

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

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

-- 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)?

7 голосов
/ 03 октября 2013
DELETE
FROM
    table_name T1
WHERE
    rowid > (
        SELECT
            min(rowid)
        FROM
            table_name T2
        WHERE
            T1.column_name = T2.column_name
    );
6 голосов
/ 02 января 2014
DELETE 
FROM MyTable
WHERE NOT EXISTS (
              SELECT min(RowID)
              FROM Mytable
              WHERE (SELECT RowID 
                     FROM Mytable
                     GROUP BY Col1, Col2, Col3
                     ))
               );
6 голосов
/ 11 июля 2012
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)
6 голосов
/ 02 февраля 2016

Еще один способ сделать это: -

DELETE A
FROM   TABLE A,
       TABLE B
WHERE  A.COL1 = B.COL1
       AND A.COL2 = B.COL2
       AND A.UNIQUEFIELD > B.UNIQUEFIELD 
...