我有这个用例,我必须对进来的数据进行增量聚合。
我有一张表 A ,其中包含以下列
id,insertion_time,key,col2,col3
我必须为每个键计算result = col2 * col3,并在一小时内找到最大值,然后将另一个表 B 放到列中。
key,hour,max
所以条件是,如果我将在一段时间后运行相同的过程,如果新数据已插入表A,则该过程应仅循环处理新记录。
到目前为止我做了什么:
我创建了一个临时表 C 来存储处理为insertion_timestamp
的最后一个last_timestamp
。每个过程执行都将检查此值,并仅选择具有insertion_time > last_timestamp
的条目。
然后proc将执行以下操作:
检查B
中是否存在(key,hour)对的条目a)如果存在 - 如果新col1 * col2值大于现有值,则更新条目 b)如果没有,请插入条目
这是在关系数据库中进行增量聚合的正确方法吗?或者有更好的方法吗?
由于
答案 0 :(得分:1)
是的,你的方法似乎没问题。我想不出任何其他会好得多的人:
PROCEDURE CALC_HOURLY_MAX
IS
l_last_timestamp DATE;
l_max_insertion_time DATE;
l_value NUMBER;
BEGIN
SELECT last_timestamp into l_last_timestamp FROM ...;
FOR r IN (
SELECT MAX(col2 * col3) max_value, key,
TRUNC(insertion_time, 'HH24') hour,
MAX(insertion_time) max_insertion_time
FROM A
WHERE insertion_time > l_last_timestamp
GROUP BY key, TRUNC(insertion_time, 'HH24')
) LOOP
BEGIN
SELECT max into l_value FROM B where key = r.key and hour = r.hour;
IF l_value < r.max_value THEN
UPDATE B set max = r.max_value where key = r.key and hour = r.hour;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO B (key, hour, max) VALUES(r.key, r.hour, r.max_value);
END;
IF l_max_insertion_time is null OR l_max_insertion_time < r.max_insertion_time THEN
l_max_insertion_time := r.max_insertion_time;
END IF;
END LOOP;
-- store highest processed insertion time
UPDATE XX SET last_timestamp = l_max_insertion_time WHERE ...;
END;
请注意,此代码可能无法编译,因为列名称MAX和HOUR在Oracle中作为符号。您可能想要选择不同的名称。
此外,如果您的交易所用时间不同,那么插入时间(从仅查看已提交数据的其他交易中看到)可能不会严格增加。因此,进一步选择回到过去可能是一个很好的方法,例如:
WHERE insertion_time > l_last_timestamp - 3 / 24 / 3600