从没有主键的SQL表中删除重复记录

时间:2009-06-12 07:12:07

标签: sql sql-server-2005 tsql duplicate-removal

我的下表中包含以下记录

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

任何人都可以帮我构建查询以删除那些重复的记录

提前致谢

19 个答案:

答案 0 :(得分:71)

很简单。我在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

答案 1 :(得分:53)

添加主键(下面的代码)

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

考虑为什么你不想保留那个主键。


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

答案 2 :(得分: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 )

答案 3 :(得分: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 ;

这将更新表并删除表中的所有重复项!

答案 4 :(得分:7)

select distinct * into newtablename from oldtablename

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

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

答案 5 :(得分:6)

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

就像Josh所说 - 即使你知道重复,删除它们也是不可能的,因为如果它与另一条记录完全相同,你实际上不能引用特定的记录。

答案 6 :(得分: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子句;你可以在这里放任何列名。如果您希望更改哪些结果被视为重复(例如保留最早或最近等),则此处使用的列很重要;即您要指定订单,以便您希望保留的记录在结果中排​​在第一位。

答案 7 :(得分: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

答案 8 :(得分:2)

在查询下方易于使用

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

答案 9 :(得分: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

删除它们会比较棘手,因为数据中没有任何内容可以在delete语句中用来区分重复项。我怀疑答案将涉及row_number()或添加标识列。

答案 10 :(得分:0)

从(选择ROW_NUMBER()OVer(按Empid顺序按Empid顺序按emppid划分)从雇员中删除)sub 其中sub.cnt> 1

答案 11 :(得分:0)

拥有一个没有主键的数据库表真的会说非常糟糕...所以在你添加一个(ALTER TABLE)之后

运行此操作,直到您看不到任何重复的记录(这是HUNT 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] )

答案 12 :(得分:0)

表ID和名称中有两列,其中名称以不同的ID重复,因此您可以使用此查询: 。

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

答案 13 :(得分: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)

答案 14 :(得分:0)

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

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

答案 15 :(得分:-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

答案 16 :(得分:-1)

从其中rowid所在的雇员中删除(从(选择rowid,从(选择rowid,count(emp_name)作为雇员组中的emp_id,emp_name)作为name_count的名称_count,其中name_count> 1)选择rowid))

答案 17 :(得分:-2)

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

使用此功能我们可以删除重复记录

答案 18 :(得分:-3)

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

@ here'b'是唯一性的列名, @ here'test'是索引名称。