2009-06-12 75 views
44

我有如下表下面的记录在它删除从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字段中具有相同值的重复记录。

例如:的Emp ID 5

任何一个可以帮助我来构建查询,删除那些重复的记录提前

感谢

+0

你可以*添加*主键? 你正在使用什么数据库系统?甲骨文?请在您的问题中指定! – 2009-06-12 07:19:47

+2

如果它具有相同的EmpID和EmpSSn,但名称不同,该怎么办? – cjk 2009-06-12 07:24:29

+0

它的SQL服务器2005 – Shyju 2009-06-12 08:02:58

回答

51

添加主键(下面的代码)

运行正确删除(下面的代码)

考虑为什么你woudln't要保持该主键。


假设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 
6

您可以创建一个包含的select distinct临时表#tempemployeeemployee表。 然后delete from employee。 然后insert into employee select from #tempemployee

像Josh说的 - 即使你知道重复,删除它们将是无法实现的,因为如果它与另一个记录完全相同,则实际上不能引用特定记录。

+2

这里只有一招:如果名称不同但ID/SSN匹配。你必须以某种方式选择一个,因为区别对此没有帮助。 – Josh 2009-06-12 07:19:39

+1

+1这是最直接,最便携的解决方案。 OP没有说明他使用什么品牌的数据库。 – 2009-06-12 07:22:21

+0

@Josh:从OP的样本看来,这看起来不是问题。所有列中的重复行都是相同的。 – 2009-06-12 07:23:21

0

我不是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 

删除它们会更棘手,因为在删除语句中可以使用任何数据来区分重复项。我怀疑答案会涉及row_number()或添加一个标识列。

22

使用行号重复的记录进行区分。保持第一行编号为的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) 
-1
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 
2

如果您不希望创建您可以在SQL Server中使用top命令一个新的主键:

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 
0
create unique clustered index Employee_idx 
on Employee (EmpId,EmpSSN) 
with ignore_dup_key

如果您不需要它,您可以删除索引。

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

@这里的 'B' 是列名的唯一性, @这里 '测试' 是索引名。

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

利用这一点,我们可以删除重复记录

69

这是非常简单的。我在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 
9
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 ; 

这将更新表,并从表中删除所有重复!

6
select distinct * into newtablename from oldtablename 

现在,newtablename将没有重复的记录。

只需在sql server的对象资源管理器中按F2键即可更改表名(newtablename)。

0

没有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) 
0

中有一个表ID和名称,这里的名字用不同的ID重复所以你可以使用这个查询两列: 。 。

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

有没有主键的数据库表真的和会说非常不好的做法......所以加一个(ALTER TABLE)

运行后,你,直到你看不到任何更多的重复记录(即是具有COUNT的目的)

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

1

ITS容易使用下面查询

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 
3

代码

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的任何东西;即重复;不是原来的。

对于有效的语法,row_number窗口函数的order by子句是必需的;你可以在这里输入任何列名称。如果您希望更改哪些结果被视为重复(例如保留最早或最近等),那么这里使用的列确实很重要;即您想要指定顺序,以便您希望保留的记录在结果中排​​在第一位。