2011-06-23 41 views
3

我有表名TABLE1包含重复的记录,如下所示:Oracle PL/SQL - 如何删除SQL表中的多个重复记录?

ID TYPE AMOUNT NUMBER  DATE 
--- ---- ------ ------ --------- 
1 AAA 10.00 AAA123 22-JUN-11 
2 AAA 2.00 AAA123 22-JUN-11 
3 AAA 10.00 AAA123 22-JUN-11 
4 AAA 2.00 AAA123 22-JUN-11 
5 AAA 10.00 AAA123 22-JUN-11 
6 AAA 2.00 AAA123 22-JUN-11 
7 AAA 10.00 AAA123 22-JUN-11 
8 AAA 2.00 AAA123 22-JUN-11 
... ...  ... ...  ... 
100 AAA 10.00 AAA123 22-JUN-11 
101 AAA 2.00 AAA123 22-JUN-11 

在这种情况下,我想使用SQL删除所有重复组合的行,除了两个或/通过PL/SQL其中AMOUNT(10.00和2.00)。另外,含有不同量的重复recordes可以多于两个,如下面所示是:

ID TYPE AMOUNT NUMBER  DATE 
--- ---- ------ ------ --------- 
1 AAA 10.00 AAA123 22-JUN-11 
2 AAA 2.00 AAA123 22-JUN-11 
3 AAA 15.00 AAA123 22-JUN-11 
4 AAA 25.50 AAA123 22-JUN-11 
5 AAA 10.00 AAA123 22-JUN-11 
6 AAA 2.00 AAA123 22-JUN-11 
7 AAA 15.00 AAA123 22-JUN-11 
8 AAA 25.50 AAA123 22-JUN-11 
... 

在上述例子中,我只需要4出8条记录,其中量应保持4条记录(10.00到删除,2.00,15.00和25.50)。换句话说,我在一个表中有多组重复项(一个为2个记录,另一个为4个等) - 存在多个存在的多个行。

+0

那么列有助于重复?只有金额? – Chandu

+0

当答案确实只使用SQL时,社区对标记PLSQL时会不满。对于什么版本的Oracle? –

回答

2

DATE列是唯一需要更多信息的列;以其他方式使用:

DELETE FROM YOUR_TABLE 
WHERE EXISTS (SELECT NULL 
       FROM YOUR_TABLE t 
       WHERE t.type = YOUR_TABLE.type 
        AND t.amount = YOUR_TABLE.amount 
        AND t.number = YOUR_TABLE.number 
        AND t.date = YOUR_TABLE.date 
      GROUP BY t.type, t.amount, t.number, t.date 
       HAVING MIN(t.id) != YOUR_TABLE.id) 

YOUR_TABLE.列引用指的是外YOUR_TABLE,要执行的表上的删除是。这给它一个相关的子查询效果,但EXISTS不完全是这样。

3

试试这个:

DELETE 
    FROM TABLE1 
    WHERE ROWID IN 
    (
     SELECT ROW_ID_VAL 
      FROM 
      (
       SELECT a.*, 
         RANK() OVER(PARTITION BY AMOUNT ORDER BY ID DESC) RN, ROWID row_id_val 
        FROM TABLE1 a 
      ) 
      WHERE rn <> 1 
    ) 
+0

在这种情况下'ROW_NUMBER'可能是更好的选择? –

+0

@OMG Pointes:我认为Id字段是唯一的,并且RANK仍然正常,因为我使用ID在窗口中排序数据。 – Chandu

+0

确实 - 不介意我,咖啡之前(tm) –

1

一种方法就可以按照举例如下:

每一行都有一个唯一的(row id)。您可以识别当然重复的行,然后根据(row id)删除重复的行。只需键入以下SELECT声明透露重复的行ID:

SELECT rowid from table_name;

0
DECLARE 

BEGIN 

    for rec_ in (
       SELECT type, amount, number, date , count(1) record_count 
        FROM table 1 
        GROUP BY type, amount, number, date 
       HAVING count(1) > 1) loop 

     counter_ := 0; 

     for rec2_ in (select * from table1 where rec_.type = type 
              and rec_.amount = amount 
              and rec_.number = number 
              and rec_.date = date) loop 

      counter_ := counter_ + 1;    
      exit when counter_ = rec_.record_count; 
      delete from table1 where id = rec2_.id; 
     End loop; 

    end loop; 
END;