Sql Oracle 10g中有条件的重复数据删除
我需要做的是删除重复的ID-Sql Oracle 10g中有条件的重复数据删除,sql,oracle,Sql,Oracle,我需要做的是删除重复的ID- 如果重复的id记录具有值(attrib1=除-999之外的任何值),则删除较低的序号(在上面的示例id=16中) 如果-999与非-999一起出现(在上面的示例id=15中),则删除值为-999的记录 如果对于重复记录,所有记录都存在“attrib1=-999”值,则删除较低的序号(在上面的示例id=17中) 跳过非重复id(在上面的示例id=18和19中) 在下面的上述示例中,应删除序号1、序号3和序号5 数据库-Oracle 10g 下面的查询为我提供了部分
- 如果重复的id记录具有值(attrib1=除-999之外的任何值),则删除较低的序号(在上面的示例id=16中)
- 如果-999与非-999一起出现(在上面的示例id=15中),则删除值为-999的记录
- 如果对于重复记录,所有记录都存在“attrib1=-999”值,则删除较低的序号(在上面的示例id=17中)
- 跳过非重复id(在上面的示例id=18和19中)
CREATE TABLE testdup
(seq_no NUMBER,
ID NUMBER,
attrib1 NUMBER,
attrib2 NUMBER);
INSERT INTO testdup
VALUES (2, 15, 1211, 1250);
INSERT INTO testdup
VALUES (1, 15, -999, -999);
INSERT INTO testdup
VALUES (3, 16, 1234, 1234);
INSERT INTO testdup
VALUES (4, 16, 1234, -1234);
INSERT INTO testdup
VALUES (5, 17, -999, -999);
INSERT INTO testdup
VALUES (6, 17, -999, -999);
INSERT INTO testdup
VALUES (7, 18, -999, -999);
INSERT INTO testdup
VALUES (8, 19, 741, -715);
COMMIT ;
我在玩弄分析函数,找到了解决办法,把它附在这里供其他人参考
SELECT seq_no, ID, attrib1,
ROW_NUMBER () OVER (PARTITION BY ID, ID ORDER BY CASE
WHEN attrib1 = -999
THEN 999999999
ELSE TO_NUMBER (attrib1)
END) rn
FROM testdup order by 1
我相信你想要
SELECT seq_no, ID, attrib1,
ROW_NUMBER () OVER (PARTITION BY ID ORDER BY CASE
WHEN attrib1 = -999
THEN 999999999
ELSE TO_NUMBER (attrib1)
END ASC,
seq_no DESC) rn
FROM testdup
下面是一个尝试:
delete from testdup where rowid in (
select
coalesce(
case when rowid_999_min is not null and
rowid_999_max is not null and
rowid_999_min != rowid_999_max
then null
else rowid_999_max
end,
rowid_min_seq
)
from (
select
min(case when attrib1 = -999 then rowid end) rowid_999_min,
max(case when attrib1 = -999 then rowid end) rowid_999_max,
min(rowid) keep (dense_rank first order by seq_no) rowid_min_seq
from
testdup
group by
id
having
count(*) > 1
)
);
with
子句允许我在一组类似的ID中知道它们是否只包含-999个值。然后,我对每个条件都有一个查询
结果是:
with w as
(
select t.id,
case when sum(case when t.attrib1 = -999 then 1 else 0 end) > 0 then 1 else 0 end exists999,
case when min(t.attrib1) = -999 and max(t.attrib1) = -999 then 1 else 0 end only999
from testdup t
group by t.id
having count(*) > 1
)
select 'Only -999 values, removed min seq_no' reason, min(t.seq_no) removed
from testdup t, w
where w.id = t.id
and w.only999 = 1
group by t.id
union all
select 'No -999 values, removed min seq_no' reason, min(t.seq_no) removed
from testdup t, w
where w.id = t.id
and w.exists999 = 0
group by t.id
union all
select 'Some -999 values, removed seq_no with this value' reason, t.seq_no removed
from testdup t, w
where w.id = t.id
and w.exists999 = 1
and w.only999 = 0
and t.attrib1 = -999
;
那么您的问题是什么呢?
attrib2
是否以某种方式影响了所需的删除?如果我正确地理解了您的需求,那么它就不存在了。@RenéNyffenegger-attrib2与deletion@Jens-我正在尝试按分区,但似乎stuckid=17同时具有attrib1=-999
,这与您在提问方法中所述的相反。。它给出了期望的结果:)
REASON REMOVED
1 Only -999 values, removed min seq_no 5
2 No -999 values, removed min seq_no 3
3 Some -999 values, removed seq_no with this value 1