Удаление дубликатов записей из таблицы SQL без первичного ключа

У меня есть таблица ниже с приведенными ниже записями в ней

create table employee
(
 EmpId number,
 EmpName varchar2(10),
 EmpSSN varchar2(11)
);

insert into employee values(1, 'Jack', '555-55-5555');
insert into employee values (2, 'Joe', '555-56-5555');
insert into employee values (3, 'Fred', '555-57-5555');
insert into employee values (4, 'Mike', '555-58-5555');
insert into employee values (5, 'Cathy', '555-59-5555');
insert into employee values (6, 'Lisa', '555-70-5555');
insert into employee values (1, 'Jack', '555-55-5555');
insert into employee values (4, 'Mike', '555-58-5555');
insert into employee values (5, 'Cathy', '555-59-5555');
insert into employee values (6 ,'Lisa', '555-70-5555');
insert into employee values (5, 'Cathy', '555-59-5555');
insert into employee values (6, 'Lisa', '555-70-5555');

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

Ex: EMP id 5

может ли кто-нибудь помочь мне создать запрос для удаления этих дубликатов записей

спасибо заранее

17 ответов


добавить первичный ключ (код ниже)

выполнить правильное удаление (код ниже)

подумайте, почему вы не хотите хранить этот первичный ключ.


предполагая MSSQL или совместимость:

ALTER TABLE Employee ADD EmployeeID int identity(1,1) PRIMARY KEY;

WHILE EXISTS (SELECT COUNT(*) FROM Employee GROUP BY EmpID, EmpSSN HAVING COUNT(*) > 1)
BEGIN
    DELETE FROM Employee WHERE EmployeeID IN 
    (
        SELECT MIN(EmployeeID) as [DeleteID]
        FROM Employee
        GROUP BY EmpID, EmpSSN
        HAVING COUNT(*) > 1
    )
END

Это очень просто. Я пробовал в SQL Server 2008

DELETE SUB FROM
(SELECT ROW_NUMBER() OVER (PARTITION BY EmpId, EmpName, EmpSSN ORDER BY EmpId) cnt
 FROM Employee) SUB
WHERE SUB.cnt > 1

использовать номер строки, чтобы различать повторяющиеся записи. Сохраните номер первой строки для EmpID / EmpSSN и удалите остальные:

    DELETE FROM Employee a
     WHERE ROW_NUMBER() <> ( SELECT MIN( ROW_NUMBER() )
                               FROM Employee b
                              WHERE a.EmpID  = b.EmpID
                                AND a.EmpSSN = b.EmpSSN )

With duplicates

As
(Select *, ROW_NUMBER() Over (PARTITION by EmpID,EmpSSN Order by EmpID,EmpSSN) as Duplicate From Employee)

delete From duplicates

Where Duplicate > 1 ;

это обновит таблицу и удалить все дубликаты из таблицы!


select distinct * into newtablename from oldtablename

и newtablename не будет иметь повторяющихся записей.

просто измените имя таблицы(newtablename), нажав F2 в обозревателе объектов в sql server.


вы можете создать временную таблицу #tempemployee содержащий select distinct вашего employee таблица. Тогда delete from employee. Тогда insert into employee select from #tempemployee.

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


код

DELETE DUP 
FROM 
( 
    SELECT ROW_NUMBER() OVER (PARTITION BY Clientid ORDER BY Clientid ) AS Val 
    FROM ClientMaster 
) DUP 
WHERE DUP.Val > 1

объяснение

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

удалить из результатов этого внутреннего запроса, выбрав все, что не имеет номер строки 1; т. е. дубликаты; не оригинал.

на order by предложение функции окна row_number необходимо для допустимый синтаксис; здесь можно поместить любое имя столбца. Если вы хотите изменить, какой из результатов рассматривается как дубликат(например, сохранить самый ранний или самый последний и т. д.), То используемые здесь столбцы имеют значение; т. е. вы хотите указать порядок, в котором запись, которую вы хотите сохранить, будет первой в результате.


Если вы не хотите создавать новый первичный ключ, вы можете использовать команду TOP в SQL Server:

declare @ID int
while EXISTS(select count(*) from Employee group by EmpId having count(*)> 1)
begin
    select top 1 @ID = EmpId
    from Employee 
    group by EmpId
    having count(*) > 1

    DELETE TOP(1) FROM Employee WHERE EmpId = @ID
end

его простое использование ниже query

WITH Dups AS
(
  SELECT col1,col2,col3,
ROW_NUMBER() OVER(PARTITION BY col1,col2,col3 ORDER BY (SELECT 0)) AS rn
 FROM mytable
)
DELETE FROM Dups WHERE rn > 1

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

select t1.empid, t1.empssn, count(*)
from employee as t1 
inner join employee as t2 on (t1.empid=t2.empid and t1.empssn = t2.empssn)
group by t1.empid, t1.empssn
having count(*) > 1

удаление их будет сложнее, потому что в данных нет ничего, что вы могли бы использовать в инструкции delete для различения дубликатов. Я подозреваю, что ответ будет включать функции row_number() или добавление столбца идентификаторов.


create unique clustered index Employee_idx
on Employee ( EmpId,EmpSSN )
with ignore_dup_key

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


нет ID, нет rowcount() или нет temp table нужны....

WHILE 
  (
     SELECT  COUNT(*) 
     FROM TBLEMP  
     WHERE EMPNO 
            IN (SELECT empno  from tblemp group by empno having count(empno)>1)) > 1 


DELETE top(1)  
FROM TBLEMP 
WHERE EMPNO IN (SELECT empno  from tblemp group by empno having count(empno)>1)

в таблице ID и name есть два столбца, в которых имена повторяются с разными идентификаторами, поэтому вы можете использовать этот запрос: . .

DELETE FROM dbo.tbl1
WHERE id NOT IN (
     Select MIN(Id) AS namecount FROM tbl1
     GROUP BY Name
)

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

запустите это, пока вы не увидите больше дублированных записей (это цель подсчета)

DELETE FROM [TABLE_NAME] WHERE [Id] IN 
(
    SELECT MAX([Id])
    FROM [TABLE_NAME]
    GROUP BY [TARGET_COLUMN]
    HAVING COUNT(*) > 1
)


SELECT MAX([Id]),[TABLE_NAME], COUNT(*) AS dupeCount
FROM [TABLE_NAME]
GROUP BY [TABLE_NAME]
HAVING COUNT(*) > 1

MAX ([Id]) приведет к удалению последних записей (добавленных после первого создания), если вы хотите противоположное значение, что в случае необходимости удаления первых записей и оставить последнюю вставленную запись, пожалуйста, используйте MIN ([Id])


select t1.* from employee t1, employee t2 where t1.empid=t2.empid and t1.empname = t2.empname and t1.salary = t2.salary
group by t1.empid, t1.empname,t1.salary having count(*) > 1

DELETE FROM 'test' 
USING 'test' , 'test' as vtable
WHERE test.id>vtable.id and test.common_column=vtable.common_column  

используя это, мы можем удалить дубликаты записей


ALTER IGNORE TABLE test
           ADD UNIQUE INDEX 'test' ('b'); 

@ здесь 'b' - имя столбца уникальности, @ здесь "test" - это имя индекса.