2011-06-23 2 views
3

Je nom table Table1 qui contient des enregistrements en double comme indiqué ci-dessous:Oracle PL/SQL - Comment supprimer plusieurs enregistrements en double dans la table 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 

Dans ce cas, je voudrais supprimer TOUTES les lignes de combinaison en double, sauf deux en utilisant SQL ou/via PL/SQL où MONTANT (10.00 et 2,00). En outre, les Recordes en double contenant différentes quantités pourraient être plus de deux comme indiqué ci-dessous:

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

Dans l'exemple ci-dessus, je dois supprimer seulement 4 sur 8 dossiers, où MONTANT doit rester 4 dossiers (10.00 , 2,00, 15,00 et 25,50). En d'autres termes, j'ai plusieurs groupes de doublons dans une table (2 enregistrements pour un, 4 pour un autre, etc.) - plusieurs lignes où plusieurs existent.

+0

Alors les colonnes contribuent à DUPLICATES? Seul montant? – Chandu

+0

La communauté désapprouve le marquage de PLSQL lorsque la réponse n'utilise réellement que SQL. Pour quelle version d'Oracle? –

Répondre

2

La colonne DATE est la seule qui nécessite plus d'informations; utiliser autrement:

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) 

Les YOUR_TABLE. références de colonne se réfèrent à la YOUR_TABLE externe, la table la suppression est à effectuer sur. Cela lui donne un effet de sous-requête corrélé, mais EXISTS ne fonctionne pas comme ça.

3

Essayez ceci:

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' pourrait être un meilleur choix dans cette situation? –

+0

@OMG Pointes: Je présume que le champ Id est unique et que RANK shuold est toujours correct car je commande les données dans une fenêtre en utilisant ID. – Chandu

+0

Vrai - ne me dérange pas, Avant le café (tm) –

1

Une méthode que vous pouvez suivre est comme suit:

Chaque ligne a une (row id) unique. Vous pouvez bien sûr identifier les lignes dupliquées, puis supprimer les lignes dupliquées sur la base de (row id). Il suffit de taper l'instruction suivante SELECT pour révéler l'ID rows dupliquée:

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