增量聚合:PL / SQL

时间:2014-01-26 10:05:57

标签: oracle stored-procedures plsql

我有这个用例,我必须对进来的数据进行增量聚合。

我有一张表 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将执行以下操作:

  1. 从表C
  2. 获取条目last_timestamp
  3. 按键和小时选择col1 * col2组的最大值,其中insertion_timestamp> lasttimestamp
  4. 每个结果的
  5. 检查B

    中是否存在(key,hour)对的条目

    a)如果存在 - 如果新col1 * col2值大于现有值,则更新条目 b)如果没有,请插入条目

  6. 这是在关系数据库中进行增量聚合的正确方法吗?或者有更好的方法吗?

    由于

1 个答案:

答案 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
相关问题