【问题标题】:Keep the last 20 records and delete other records in oracle sql保留最后20条记录并删除oracle sql中的其他记录
【发布时间】:2016-06-14 13:09:29
【问题描述】:

我想保留VMR 表中的最后 20 条记录并删除所有其他记录。 VMR 表有5000000 记录并且它还在增长。我还有 VMR 表中有 date datatype 的 create_date 列,并且它具有非唯一索引。我尝试使用 rownum 删除记录并使用以下查询保留最后 20 条记录,但删除时间太长。有没有其他方法可以更快地运行查询。

delete from VMR
 where rowid not in 
       (select rowid
          from VMR
         where rownum <=20);

【问题讨论】:

    标签: oracle timestamp sql-delete rownum rowid


    【解决方案1】:

    只是为了展示一个替代方案:

    -- get 20 last records and remember them
    create table vmr20 as
      select * from vmr order by create_date desc fetch first 20 rows only;
    
    -- empty table via DDL which should be fastest
    truncate vmr;
    
    -- re-insert the last 20 rows
    insert into vmr
      select * from vmr20;
    
    -- delete temp table
    drop table vmr20;
    

    【讨论】:

    • 使用截断的一个缺点是你不能ROLLBACK
    • 是的,这是真的。因此,必须确保不要忘记在截断之前执行第一条语句:-) 并且表完全为空的时间很短。所以这应该在没有使用表的时候完成。
    【解决方案2】:

    尝试使用ROW_NUMBER()

    WITH CTE AS (
    SELECT t.*,
           ROW_NUMBER() OVER(ORDER BY create_date DESC) as rnk
    FROM VMR t)
    DELETE FROM CTE 
    WHERE CTE.rnk > 20
    

    【讨论】:

    • 您能解释一下查询吗?它对我来说看起来很复杂,我从未在查询中使用过分区
    • 它实际上并没有使用分区,这个分区就像一个GROUP BY子句来对行进行排名,你可以看到我在那里使用11,因为它没关系。这只是将第一行列为 1,将第二行列为 2 和 ETC.. 然后使用这些数据,删除大于 20 的所有内容。@Andrew
    • 如果要按常量字面值进行分区,为什么要包含 PARTITION BY 子句?它不做任何事情,只需将其删除即可。
    • 我认为存在混淆。前 20 条记录意味着您必须考虑我运行此查询的过去 20 条记录,但它还包括我不想删除的过去 20 行。我将在我的问题中对此进行编辑。
    • @Andrew 我更新了答案,您没有在查询中包含它,所以我认为顺序无关紧要。现在它将保持create_date的最新20条记录。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-20
    • 2012-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多