Sql 甲骨文密秩

Sql 甲骨文密秩,sql,oracle,dml,Sql,Oracle,Dml,我需要根据ID和时间列删除重复的行。我只需要保留最新时间的记录。如果有两条记录的最大时间,我可以保留其中任何一条记录并删除该组中的所有其他记录。请在下面查找我的输入数据 ID TIMES 123 13/01/2018 123 14/01/2018 123 15/01/2018 345 14/01/2018 567 20/01/2018 567 20/01/2018 879 NULL 879 21/01/2018 我已经为相同的问题编写了一个查询,但它不适用于ID=567的情况,因为它们在ti

我需要根据ID和时间列删除重复的行。我只需要保留最新时间的记录。如果有两条记录的最大时间,我可以保留其中任何一条记录并删除该组中的所有其他记录。请在下面查找我的输入数据

ID  TIMES
123 13/01/2018
123 14/01/2018
123 15/01/2018
345 14/01/2018
567 20/01/2018
567 20/01/2018
879 NULL
879 21/01/2018
我已经为相同的问题编写了一个查询,但它不适用于ID=567的情况,因为它们在times列中都有相同的值。请在下面找到我的问题

delete FROM table where (ID,times) in( 
  SELECT ID,times, 
    RANK() OVER (PARTITION BY ID ORDER BY times DESC NULLS LAST) dest_rank
    FROM TABLE 
  ) WHERE dest_rank <> 1
有什么办法可以做到这一点。

这里有一种方法:

delete t from t
    where rowid <> (select max(rowid) keep (dense_rank first order by times desc)
                    from t t2
                    where t2.id = t.id
                   );

您可以通过以下方式获得成功:

我只是

delete demo where rowid in
( select lag(rowid) over (partition by id order by times nulls first) from demo  );

您没有说希望如何处理空值。如果要保留日期为null的行,请将nulls first更改为nulls last。

我认为我们需要使用rowid,而不是rowid=@GIN。好主意。你可以很容易地解决你的问题——这比公认的答案更糟糕。问题是您使用了RANK函数。您应该改用ROW_NUMBER函数。正如您所发现的,RANK函数将显示与相同级别的关系,因此这对您没有帮助。在打领带的情况下,ROW_NUMBER会任意为各行分配不同的号码,这就是您所需要的。
delete mytable where (rowid) in
(
  select t1.rowid from mytable t1
   where times <
  (
  select max(times)
    from mytable t2
   where t2.id = t1.id  
     and t2.times != t1.times -- for non-matching records of times
  )
  union all
  select t1.rowid from mytable t1
   where rowid <
  (
  select max(rowid)
    from mytable t2
   where t2.id = t1.id
     and t2.times = t1.times  -- for matching records of times
  )
);
delete demo where rowid in
( select lag(rowid) over (partition by id order by times nulls first) from demo  );