Oracle Update使用Lag功能

时间:2016-11-23 02:08:52

标签: sql oracle lag

我尝试在lag维度中使用update函数SCD2有效开始日期。我试图使用子查询基于PK自行加入表。更新不会根据前一个结束日期更新,而只会更新为默认值(本身)。当我删除默认值时,我得到一个错误,因为有效的开始日期不能为空。当我只使用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'

表:

enter image description here

期望的结果:

enter image description here

1 个答案:

答案 0 :(得分:0)

可能存在其中一个原因导致您的更新无效。我不知道你桌子的确切结构。您尚未提供样本数据。如果您的account_dim_key对于每一行都是唯一的,则select lag() ... from schema.d_account ac2 where ac1.account_dim_key = ac2.account_dim_key)将返回一行,您将有效地将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)将返回多行,Oracle会抱怨UPDATE不可能(有一个特定的错误消息,我做不记得确切的措辞。

要使查询有效,您需要使用其他方法:

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:根据您对表的索引,您可能会获得更好的性能

更新:上述查询可能会给您带来不良影响。下面的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;