Oracle 更新使用滞后功能

Oracle Update using Lag function

我正在尝试使用 lag 函数在 SCD2 维度中 update 有效开始日期。我正在尝试使用子查询根据 PK 自行加入 table。更新不会根据之前的结束日期进行更新,而只会更新为默认值(它本身)。当我删除默认值时出现错误,因为有效开始日期不能为空。当我只使用 select 时,我得到了想要的结果。

非常感谢任何帮助,我相信这很简单!

update schema.d_account ac1
set effective_start_dt = (select lag(effective_end_dt, 1, effective_start_dt) over(partition by id order by effective_end_dt asc) 
                          from schema.d_account ac2
                          where ac1.account_dim_key = ac2.account_dim_key),
audit_last_update_dt = sysdate,
where id in '0013600000USKLqAAP'

Table:

想要的结果:

您的更新无法正常工作可能是以下原因之一。我不知道你的table的确切结构。您尚未提供示例数据。如果您的 account_dim_key 对于每一行都是唯一的,那么 select lag() ... from schema.d_account ac2 where ac1.account_dim_key = ac2.account_dim_key) 将 return 一行,您将有效地将 effective_start_dt 更新为 effective_start_dt (默认值滞后函数)

如果您作为示例提供的所有这些行的 account_dim_key 都相同,那么 select lag() ... from schema.d_account ac2 where ac1.account_dim_key = ac2.account_dim_key) 将 return 多行并且 Oracle 将抱怨无法更新(有具体报错信息,具体写法不记得了。

要使您的查询正常工作,您需要使用不同的方法:

update schema.d_account ac1
set effective_start_dt = (select prev_dt from
                          (select lag(effective_end_dt, 1, effective_start_dt) over(partition by id order by effective_end_dt asc) as prev_dt
                          , ROWID as rid
                          from schema.d_account ac2) a where a.rid = ROWID),
audit_last_update_dt = sysdate,
where id in '0013600000USKLqAAP'

所以,基本上您有一个子查询 a,其中包含您构建前一个日期的 ROWID 列。对于 UPDATE 语句,您通过 ROWID 加入此子查询。

注意:如果您的 account_dim_key 对于每一行都是唯一的,您可以使用它代替 ROWID:您可能会获得更好的性能,具体取决于您为 table[=17 设置的索引=]

更新:上述查询可能会给您带来糟糕的表现。使用下面的 MERGE 语句会更好:

MERGE INTO (SELECT id, effective_start_dt, ROWID rid, audit_last_update_dt 
   FROM schema.d_account WHERE id in '0013600000USKLqAAP') ac1
USING (select lag(effective_end_dt, 1, effective_start_dt) over(partition by id order by effective_end_dt asc) as prev_dt
      , ROWID as rid
      from schema.d_account) ac2
ON (ac1.rid = ac2.rid) 
WHEN MATCHED THEN UPDATE SET ac1.effective_start_dt = ac2.prev_dt,
ac1.audit_last_update_dt = sysdate;