Oracle SQL——如何使用首选项删除部分重复项
Posted
技术标签:
【中文标题】Oracle SQL——如何使用首选项删除部分重复项【英文标题】:Oracle SQL -- how to delete partial duplicates with a preference 【发布时间】:2017-12-28 06:22:37 【问题描述】:您能帮我从表中删除重复项(部分)吗?我有一个包含 5 列的表。在这张表中,我有重复项——但只有 4 列是相同的,其中一列(field5)是不同的。那就是:
F1 F2 F3 F4 F5
A1 A2 A3 A4 103
A1 A2 A3 A4 3
因此,对于重复项,4 列/字段是相同的,除了第 5 个。我想删除包含数字“103”的行,即更高的数字。我怎样才能做到这一点?
如果这是一个正常的副本,我会使用 max(rowid) 并删除该行。但是现在这可以删除包含较低数字而不是较高数字的行。
我能想到的一种方法是创建一个新表,其中包含重复的行,并且 Field5 在该表中具有更高的数字。然后通过将其与此新表进行比较来从原始表中删除行。但这对我来说似乎不是很好的解决方案——尤其是如果原始表很大,这可能需要很长时间。
任何帮助将不胜感激。谢谢。
【问题讨论】:
【参考方案1】:想法是记录F1,F2,F3,F4
的每个组合并删除其余的。
试试这个:
DELETE FROM TABLE_NAME WHERE ROWID IN
(SELECT ROWID FROM
(SELECT ROWID, row_number() OVER(PARTITION BY F1,F2,F3,F4 ORDER BY F5) RN
FROM TABLE_NAME)
WHERE RN<>1);
【讨论】:
这会引发 ORA-01446:无法从具有 DISTINCT、GROUP BY 等的视图中选择 ROWID 或对其进行采样。但是,如果您删除 ROWNUM,它将起作用。 非常感谢您的帖子!这个完美。上一篇文章提出了 Littlefoot 指定的错误。如果我可以选择,这对我来说将是最好的解决方案:)【参考方案2】:这个怎么样?
SQL> select * from test order by f1, f5;
F1 F2 F3 F4 F5
-- -- -- -- ----------
a1 a2 a3 a4 3
a1 a2 a3 a4 50 --> delete
a1 a2 a3 a4 103 --> delete
b1 b2 b3 b4 2
b1 b2 b3 b4 200 --> delete
c1 c2 c3 c4 1
6 rows selected.
SQL> delete from test t
2 where rowid not in (select rowid
3 from test t1
4 where t1.f1 = t.f1
5 and t1.f2 = t.f2
6 and t1.f3 = t.f3
7 and t1.f4 = t.f4
8 and t1.f5 =
9 (select min (t2.f5)
10 from test t2
11 where t2.f1 = t.f1
12 and t2.f2 = t.f2
13 and t2.f3 = t.f3
14 and t2.f4 = t.f4));
3 rows deleted.
SQL> select * from test order by f1, f5;
F1 F2 F3 F4 F5
-- -- -- -- ----------
a1 a2 a3 a4 3
b1 b2 b3 b4 2
c1 c2 c3 c4 1
SQL>
【讨论】:
非常感谢小脚!你的回答太棒了!并感谢您在第一篇文章中指出问题。我不知道这可以通过我自己知道的东西/概念来解决:) 所以,感谢指出这样的解决方案。此解决方案的唯一缺点是,当表中有很多列时,行数过多。【参考方案3】:我通常只是这样做:
delete demo
where rowid in
( select lead(rowid) over (partition by f1, f2, f3, f4 order by f5) as next_rowid
from demo );
也就是说,在其(f1, f2, f3, f4)
组中按f5
的顺序删除每个“下一个”行。
【讨论】:
感谢您的回答!这是一个有趣的解决方案。我实际上首先有疑问,但看起来它按预期工作。以上是关于Oracle SQL——如何使用首选项删除部分重复项的主要内容,如果未能解决你的问题,请参考以下文章