简体   繁体   中英

How to delete duplicates in Oracle?

I am trying to remove duplicate rows in my table but it given me an error saying

SQL Error: ORA-01732: data manipulation operation not legal on this view
01732. 00000 -  "data manipulation operation not legal on this view"
*Cause:    
*Action:

Below is my query:

delete from
(
SELECT A.*,
row_number() over (partition by x,y order by y) as dup
FROM table A
WHERE x='13' AND EXTRACT(YEAR FROM y)='2020'
) A
where dup>1

If y is unique then you would typically use:

delete from a
    where x = '13' and
          y >= date '2020-01-01' and
          y < date '2021-01-01' and
          rowid > (select min(a2.y)
                   from a a2
                   where a2.x = a.x and a2.y >=  date '2020-01-01' and y < date '2021-01-01'
                  );

You can also use rowid -- which works even if y is not unique:

delete from a
    where x = '13' and
          y >= date '2020-01-01' and
          y < date '2021-01-01' and
          y <> (select min(rowid) keep (dense_rank first order by y)
               from a a2
               where a2.x = a.x and a2.y >=  date '2020-01-01' and y < date '2021-01-01'
              );

You could select the rowid s you want to delete and then use an in condition to delete them:

DELETE FROM tablea
WHERE  rowid IN (SELECT rowid
                 FROM   (SELECT rowid, ROW_NUMBER() OVER (PARTITION BY x, y ORDER BY y) AS dup

                         FORM   tablea
                         WHERE  x = '13' AND EXTRACT(YEAR FROM y) = '2020')
                 WHERE  dup > 1)

A Simple technique is to use the EXISTS as follows:

DELETE FROM TABLE_A A
WHERE A.X = '13' 
  AND A.Y >= TRUNC(SYSDATE,'YY')  -- 01-01-2020
  AND A.Y < TRUNC(ADD_MONTHS(SYSDATE,12),'YY') -- 01-01-2021
  AND EXISTS (SELECT 1 
                FROM TABLE_A AA
               WHERE AA.X = A.X
                 AND AA.Y = A.Y
                 AND AA.ROWID > A.ROWID);

Another standard pattern is:

delete sometable
where  rowid in (
       ( select lead(rowid) over (partition by y order by z) as dup
         from   sometable a
         where  x = '13'
         and    ... )

where y is the duplicated key or keys (eg customer_id ) and z is an ordering key the lets you pick the 'first' or 'last' row to keep (eg created_date , if you have the same customer created on multiple days and you want to keep the first one and delete the rest).

This part of your example didn't seem to make sense:

(partition by x,y order by y)

because everything in each partition already has the same value for x and y . You would want to order by something that isn't part of the partition key.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM