【问题标题】:How to keep records in an Oracle table based on the nearest date如何根据最近的日期将记录保存在 Oracle 表中
【发布时间】:2017-10-20 02:39:30
【问题描述】:

我有一个 Oracle 表 T,其中有多个具有不同开始日期的记录。我想删除所有,但保留 col1、col2、col3 的相同组合中日期最大的那个。在此示例中,我想保留日期为 31-May-17 的一个并删除另外两个。在不创建另一个临时表的情况下,在单个查询中实现此目标的最佳方法是什么?

测试脚本 -

create table t 
(col1 number(10)
,col2 number(10)
,col3 number(10)
,col4 number(10)
,col5 date
);

insert into t values (15731,467,4087,14427,'09-Apr-17');
insert into t values (15731,467,4087,17828,'31-May-17');
insert into t values (15731,467,4087,15499,'16-Apr-17');
commit;

select * from t;[enter image description here][1]

根据上面的数据,我想只保留日期为 31-May-17 的记录,因为这是具有相同 col1、col2、col3 组合的日期中最大的日期,并删除其余两个日期桌子。请注意,此表上还有数百万条其他记录,例如上面的记录。 如果这对 Oracle 专家来说太天真了,请道歉,但我是在这个地方尝试使用 Oracle db 的新手。

【问题讨论】:

  • 从现在开始,你将如何在相同的时间距离内打破多条记录?
  • 这正是我意识到实现的挑战——如果时间位移相同怎么办?为了使它更简单,我更改了我的标准以删除具有相同键 col1、col2 和 col3 的旧日期,并保留该键组合中日期最大的记录。谢谢指出!!
  • 请更改您的描述,明确如何处理关系。请举个例子来说明这种情况。

标签: sql oracle select oracle12c


【解决方案1】:

您可以按日期和sysdate 之间的差值的绝对值对行进行排序。然后,您可以使用rowid 伪列来关联查询和删除语句:

DELETE FROM t
WHERE  rowid NOT IN (SELECT r
                     FROM   (SELECT rowid AS r, 
                                    ROW_NUMBNER() OVER 
                                        (PARTITION BY col1, col2, col3
                                         ORDER BY ABS(SYSDATE - col5) ASC) AS rn
                             FROM   t)
                     WHERE  rn = 1)

【讨论】:

  • 这还应该包括partition by..RANK 可能而不是ROW_NUMBER
  • 我很抱歉不是很清楚,但我的意思是保留所有日期中日期最大的那个,并使用相同的 col1、col2、col3 组合,而不是找到最近的日期.
  • @vkp 鉴于 Brendon 的最后一条评论,您是对的 - 那里缺少 partition by 子句。关于 row_numberrank 问题 - 这取决于 OP 是要保留单个记录还是所有并列记录
  • 感谢 Mureinik 的 sql - 非常感谢!!我正在阅读 oracle 文档来学习按子句分区并与 row_number 一起使用。我在运行你的 sql 时遇到语法错误,尽管 oracle 正在抱怨缺少右括号!!我在挠头,它会从哪里丢失?
  • @Brendon - 在原始帖子下的评论中,OP 表示他希望将所有行与“最近”开始日期绑定。在这种情况下,应使用rank() 而不是row_number()。如果业务需求发生变化(例如,平局,只保留 COL4 中最大值的行),可以使用row_number(),在row_number()order by 子句中添加额外的排序标准.
【解决方案2】:

由于它被标记为 oracle12c,您不妨利用它的功能。例如,使用MATCH_RECOGNIZE:

delete from t
  where rowid not in (
                       select rowid
                       from   t
                         match_recognize (
                           partition by col1, col2, col3
                           order by col5 desc
                           all rows per match
                           pattern ( ^ a x* )
                           define x as x.col5 = a.col5
                         )
                     )
;

这假设您希望为 COL1、COL2、COL3 的给定组合的最新开始日期“绑定”所有行。该解决方案可以适应需求的变化。

【讨论】:

  • 感谢 Mathguy...我一直在阅读 oracle 文档中有关 Match_Recognize 函数的信息,并且很有趣他们如何开发模式匹配标准...再次感谢!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-14
  • 2015-09-06
  • 2019-03-29
  • 1970-01-01
相关资源
最近更新 更多