Удаление дубликатов записей из таблицы 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" - это имя индекса.