【问题标题】:How to delete duplicates in Oracle?如何删除Oracle中的重复项?
【发布时间】:2020-10-23 13:59:51
【问题描述】:

我正在尝试删除表中的重复行,但它给了我一个错误提示

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

以下是我的查询:

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

【问题讨论】:

  • 重复的列还是你的意思是行?顺便说一句,如果这实际上是有效的,它将删除所有匹配的行,而不仅仅是重复的。
  • 我要删除重复行

标签: sql oracle duplicates sql-delete


【解决方案1】:

如果y 是唯一的,那么您通常会使用:

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

您也可以使用rowid -- 即使y 不是唯一的也可以使用:

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

【讨论】:

    【解决方案2】:

    您可以选择要删除的rowids,然后使用in 条件删除它们:

    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)
    

    【讨论】:

      【解决方案3】:

      一个简单的技巧是使用EXISTS,如下所示:

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

      【讨论】:

        【解决方案4】:

        另一种标准模式是:

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

        其中y 是一个或多个重复键(例如customer_id),z 是一个排序键,可以让您选择要保留的“第一”或“最后”行(例如created_date,如果您多天创建了同一个客户,您希望保留第一个客户并删除其余客户)。

        您的示例的这一部分似乎没有意义:

        (partition by x,y order by y)
        

        因为每个分区中的所有内容对于xy 已经具有相同的值。您可能希望按不属于分区键的内容进行排序。

        【讨论】:

          猜你喜欢
          • 2016-02-21
          • 2021-11-08
          • 2020-09-13
          • 2020-12-21
          • 2020-04-12
          • 2015-09-27
          • 2019-02-03
          • 2020-02-17
          • 1970-01-01
          相关资源
          最近更新 更多