6

有没有人有一个优雅的 sql 语句来从表中删除重复记录,但前提是重复次数超过 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

4 回答 4

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 的“重复项”,然后分配编号 1、2、3..N,按 ID 排序。如果您只想保留 2 个“重复”,那么您需要删除那些分配了数字3,4,.. N的部分,这是由DELLETE.. WHERE rn > 2;

使用此方法,您可以更改ORDER BY以适合您的首选顺序(例如ORDER BY ID DESC),以便LATESThas rn=1,然后最新的下一个是 rn=2 等等。其余的保持不变,DELETE将仅删除最旧的,因为它们具有最高的行号。

这个密切相关的问题不同,随着条件变得更加复杂,使用 CTE 和 row_number() 变得更加简单。如果不存在适当的访问索引,性能可能仍然存在问题。

于 2009-07-24T01:01:44.760 回答
3

HAVING是你的朋友

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

于 2009-07-24T00:49:56.910 回答
1

您可以尝试以下查询:

DELETE FROM table t1 
WHERE rowid IN
(SELECT MIN(rowid) FROM table t2 GROUP BY t2.id,t2.name HAVING COUNT(rowid)>3);
于 2019-04-30T04:02:55.680 回答
0

相当晚但最简单的解决方案可能如下假设我们有表emp_dept(empid,deptid),其中有重复的行,这里我使用@Count 作为变量.. 例如允许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 或标识。因此,如果存在重复行,那么具有较高行 ID 或标识的行将被删除。并且对于没有重复的行,它无法找到较低的行ID,因此不会被删除。

于 2013-06-11T06:29:43.540 回答