SQL查询 - 如果超过3个重复,删除重复项?

时间:2009-07-24 00:47:10

标签: sql sql-server duplicates

有没有人有一个优雅的sql语句来删除表中的重复记录,但只有当x重复数超过x时?所以它允许最多2或3个副本,但就是这样吗?

目前我有一个select语句执行以下操作:

delete table
from table t
left outer join (
 select max(id) as rowid, dupcol1, dupcol2
 from table
 group by dupcol1, dupcol2
) as keeprows on t.id=keeprows.rowid
where keeprows.rowid is null

这很有效。但现在我想做的只是删除那些行,如果他们有超过2个重复。

由于

4 个答案:

答案 0 :(得分:7)

with cte as (
  select row_number() over (partition by dupcol1, dupcol2 order by ID) as rn
     from table)
delete from cte
   where rn > 2; -- or >3 etc

查询为每条记录制作一个“行号”,按(dupcol1,dupcol2)分组并按ID排序。实际上,此行号计数具有相同dupcol1和dupcol2的“重复”,然后按ID排序,然后分配数字1,2,3 .. N.如果您只想保留2个'重复',那么您需要删除分配了数字3,4,.. N的那些,这是由DELLETE.. WHERE rn > 2;

处理的部分

使用此方法,您可以更改ORDER BY以符合您的首选订单(例如ORDER BY ID DESC),以便LATEST具有rn=1,然后是最新的是rn = 2,依此类推。其余的保持不变,DELETE将只删除最旧的那些,因为它们具有最高的行号。

this closely related question不同,随着条件变得更加复杂,使用CTE和row_number()会变得更简单。如果不存在适当的访问索引,性能可能仍然存在问题。

答案 1 :(得分:3)

HAVING是你的朋友

select id, count(*) cnt from table group by id having cnt>2

答案 2 :(得分:1)

您可以尝试以下查询:

DELETE FROM table t1 
WHERE rowid IN
(SELECT MIN(rowid) FROM table t2 GROUP BY t2.id,t2.name HAVING COUNT(rowid)>3);

答案 3 :(得分:0)

很晚但最简单的解决方案可能如下  假设我们有表emp_dept(empid,deptid),它有重复的行,  在这里,我使用@Count作为varibale ..例如2重复允许然后@count = 2  在Oracle数据库

  delete from emp_dept where @Count <= ( select count(1) from emp_dept i where i.empid = emp_dept.empid and i.deptid = emp_dept.deptid and i.rowid < emp_dept.rowid ) 

在sql server或不支持row id kinda功能的任何数据库上,我们需要添加标识列以识别每一行。  说我们已经将nid添加为表格

alter table emp_dept add nid int identity(1,1) -- to add identity column

现在查询删除副本可以写成

  delete from emp_dept where @@Count <= ( select count(1) from emp_dept i where i.empid = emp_dept.empid and i.deptid = emp_dept.deptid and i.nid< emp_dept.nid ) 

这里的概念是删除存在其他行的所有行,这些行具有相似的核心值但是n或更大的较小的rowid或identity的数量。因此,如果存在重复行,则具有较高行ID或标识的行将被删除。并且对于行没有重复,它无法找到较低的行ID,因此不会被删除。