Sql Oracle 10g中有条件的重复数据删除

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-

  • 如果重复的id记录具有值(attrib1=除-999之外的任何值),则删除较低的序号(在上面的示例id=16中)
  • 如果-999与非-999一起出现(在上面的示例id=15中),则删除值为-999的记录
  • 如果对于重复记录,所有记录都存在“attrib1=-999”值,则删除较低的序号(在上面的示例id=17中)
  • 跳过非重复id(在上面的示例id=18和19中)
在下面的上述示例中,应删除序号1、序号3和序号5

数据库-Oracle 10g

下面的查询为我提供了部分输出,但当attrib1与给定id相同时,则无法删除min(seq_id)

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