【发布时间】:2021-03-09 19:06:15
【问题描述】:
我会尽量缩短查询。这涉及 2 个表 - 我们称它们为 staging_data 和 audit_data。 STAGING_DATA 有 3 列:
- user_no 与数据类型编号,
- update_date_time 数据类型为 DD-MON-YYYY HH24:MI:SS 格式的日期
- status_code 是 varchar(1)。
audit_data 表也有相同的 3 列。要求是向 audit_data 表添加 3 列
- seq_no(每个用户都是唯一的),
- active_from(不带时间格式的日期类型)
- active_to(不带时间格式的日期类型)。
有一个将数据从 staging_data 插入到 audit_data 的过程。 表 audit_data 示例
审计表中的数据应如下所示:
对于 user_no 523 的下一条记录(假设 update_date_time 为 '23-Nov-2020 10:20')seq_no 变为 3,active_from_date 变为 '23-Nov-2020',active_to 变为 31-Dec-99 和 active_to seq_no 2 的 user_no 523 变为“2020 年 11 月 22 日”。所以数据应该是这样的:
以浅绿色突出显示稍后将添加的第三条记录。
所以这是我的解决方案:我建议使用row_number() over(partition by user_no) 分析函数来获取每个用户的 seq_no。我想基于它创建一个视图,但老板不想要一个视图。他严格地想要使用一个程序。程序应检查 user_no 是否存在(在本例中为 523)。如果存在,则 seq_no 增加,并且 523 的先前记录的 active_to 更改为最新的 active_from - 1 日期。老实说 - 我不知道如何在程序中实现这一点。我知道我可以使用我对视图的查询来创建一个游标。但是添加 seq_no 和更改 active_to 日期让我感到困惑。任何人都可以指导我正确的方向吗?如果我遗漏了任何其他细节,我提前道歉。现在是午夜了,经过 8 个小时的绞尽脑汁,我非常饿!
编辑 3 月 11 日:这是我编写的将数据插入审计表的过程的代码,以应对特定 user_no 在审计表中没有记录的情况:
create or replace procedure test_aud IS
user_found_audit number;
lv_user_no AUDIT_DATA.user_no%TYPE;
cursor member_no is select distinct user_no from STAGING_DATA;
begin
open member_no;
loop
fetch member_no into lv_user_no;
exit when member_no%notfound;
select count(*) into user_found_audit from AUDIT_DATA where user_no = lv_user_no;
if user_found_audit = 0 then
insert into AUDIT_DATA(user_no, update_date_time,status_code, seq_no, last_update_date, active_from, active_to)
select user_no, update_date_time,status_code,row_number() over(partition by user_no order by UPDATE_DATE_TIME) as seqno,
to_char(trunc(update_date_time),'DD-MON-YYYY'),
to_char(trunc(update_date_time),'DD-MON-YYYY'),
lead(to_char(trunc(update_date_time)-1,'DD-MON-YYYY'),1,'31-DEC-99') over(PARTITION BY user_no ORDER BY UPDATE_DATE_TIME) from STAGING_DATA where user_no = lv_user_no;
commit;
else
dbms_output.put_line(lv_user_no||' exists in audit table');
-- to code the block when user_no exists, involves an update and insert
end if;
end loop;
close member_no;
end;
/
【问题讨论】: