Oracle 10g 中的条件重复删除

Conditional duplicate removal in Oracle 10g

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 ;

我需要做的是,删除重复的id -

在下面的例子中 seq_no 应该删除 1、3 和 5

数据库 - Oracle 10g

下面的查询给了我部分输出,但是当给定 id 的 attrib1 相同时,删除 min(seq_id) 是行不通的

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 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
;

with 子句让我知道在一组相似的 ID 中,它们是否仅包含 -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