我有一个每天都在增长的庞大数据集。对每一行的数据都有一定的更新。
Table Structure :
Id Level Data Output
-- ----- ------- ---------
1 1 12.3 12.3
1 2 42.5 522.75
1 3 129 67434.75
2 1 3.12 3.12
2 2 0.12 0.3744
2 3 32.1 12.01824
2 4 39.1 469.913184
3 1 0.83 0.83
3 2 4.21 3.4943
4 1 3.49 3.49
对于一个id,输出是数据与其先前级别的数据相乘[data * 1 for level = 1]
现在,每天获得的ID数量没有限制,也没有限制每个ID的数量。
已编辑::帮助计算此数据集的输出(值或列)。
答案 0 :(得分:0)
答案 1 :(得分:0)
我相信你提到的表使用复合键。
使用Oracle提示使用索引指向优化程序。
Update /*+ INDEX(tabName indexName) */ tabName
set column = value
where id = 1 and level = 1
非常感谢APC能够启发它想要实现的目标。 也许我应该举例说明一点
Update /*+ INDEX(tabName indexName) */ tabA t1
set output = data * exp(sum(log(select data from tabA t2 where t2.level < t1.level)
where id = 1 and level = 3
由于我们尝试在更新时选择表格
,因此不确定是否会锁定表锁定答案 2 :(得分:0)
记录中的数据不应该依赖于其他记录中的数据。如果output
是每个ID data
的运行产品,则不应存储,而是查询。 (否则,每当data
发生更新时,您都必须重新计算所有值。)我们必须努力避免数据库中的冗余,以避免一致性问题。
说完这个,你必须写一个查询。一种选择是递归查询。另一种是窗口功能。至于后者,有SUM OVER
和AVG OVER
等,但没有MULTIPLY OVER
等。所以我们必须创建这个聚合函数:
CREATE OR REPLACE TYPE AggregateProduct
AS OBJECT
(
product NUMBER,
STATIC FUNCTION ODCIAggregateInitialize(actx IN OUT AggregateProduct) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateIterate(self IN OUT AggregateProduct, val IN NUMBER) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateTerminate(self IN AggregateProduct, returnValue OUT NUMBER, flags IN NUMBER) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateMerge(self IN OUT AggregateProduct, ctx2 IN AggregateProduct) RETURN NUMBER
);
CREATE OR REPLACE TYPE BODY AggregateProduct AS
STATIC FUNCTION ODCIAggregateInitialize(actx IN OUT AggregateProduct) RETURN NUMBER IS
BEGIN
IF actx IS NULL THEN
actx := AggregateProduct(null);
ELSE
actx.product := null;
END IF;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateIterate(self IN OUT AggregateProduct, val IN NUMBER) RETURN NUMBER IS
BEGIN
IF val IS NOT NULL THEN
self.product := NVL(self.product, 1) * val;
END IF;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateTerminate(self IN AggregateProduct, ReturnValue OUT NUMBER, flags IN NUMBER) RETURN NUMBER IS
BEGIN
returnValue := self.product;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateMerge(self IN OUT AggregateProduct, ctx2 IN AggregateProduct) RETURN NUMBER IS
BEGIN
self.product := self.product * ctx2.product;
RETURN ODCIConst.Success;
END;
END;
CREATE OR REPLACE FUNCTION agg_multiply(x NUMBER) RETURN NUMBER PARALLEL_ENABLE
AGGREGATE USING AggregateProduct;
然后查询将是:
select
id, "level", data,
agg_multiply(data) over(partition by id order by "level") as output
from mytable
order by id, "level";
(顺便说一下,你应该避免使用level
作为列名,因为这是Oracle中的保留字。)
如上所述,另一个选项是递归查询,但在哪里会有趣呢? ; - )
multiplied(id, "level", data, output) as
(
select id, "level", data, data as output from mytable where "level" = 1
union all
select mytable.id, mytable."level", mytable.data, mytable.data * multiplied.output
from multiplied
join mytable on mytable.id = multiplied.id and mytable."level" = multiplied."level" + 1
)
select *
from multiplied
order by id, "level";