我只是扩展了@Denis Zhuravlev 的答案。
CH 没有专门的函数来计算累积乘法(或任何除加法之外的任意数学运算符),此外,由于这种计算的“累积”性质,无法应用现有函数来获得所需的结果。
因此需要使用对数将乘法转换为加法:
loga x*y = loga x + loga y
x*y = a(loga x + loga y)
SELECT r.1.1 row, r.1.2 rate, r.2 value, round(r.2, 2) rounded_value
FROM (
SELECT
groupArray((row, rate, rate_log)) data,
arrayMap(log -> exp10(log), arrayCumSum(data_item -> data_item.3, data)) rate_cumulative_values,
arrayJoin(arrayZip(data, rate_cumulative_values)) r
FROM (
SELECT row, rate, log10(rate) AS rate_log
FROM (
/* emulate the origin dataset */
SELECT data.1 row, data.2 rate
FROM (SELECT arrayJoin([
(1, 2), (2, 3), (3, 4), (4, 5),
(5, 1), (6, 0), (7, -1)]) AS data))
ORDER BY row));
/*
┌─row─┬─rate─┬──────────────value─┬─rounded_value─┐
│ 1 │ 2 │ 2 │ 2 │
│ 2 │ 3 │ 6 │ 6 │
│ 3 │ 4 │ 23.999999999999993 │ 24 │
│ 4 │ 5 │ 119.99999999999996 │ 120 │
│ 5 │ 1 │ 119.99999999999996 │ 120 │
│ 6 │ 0 │ 0 │ 0 │
│ 7 │ -1 │ nan │ nan │
└─────┴──────┴────────────────────┴───────────────┘
*/
同样的逻辑可以应用于计算累加除法:
x/y = a(loga x - loga y)
累计除法:
SELECT r.1.1 row, r.1.2 rate, r.2 value, round(r.2, 2) rounded_value
FROM (
SELECT
groupArray((row, rate, rate_log)) data,
arrayMap(log -> exp10(log), arrayCumSum((data_item, index) -> index = 1 ? data_item.3 : - data_item.3, data, arrayEnumerate(data))) rate_cumulative_values,
arrayJoin(arrayZip(data, rate_cumulative_values)) r
FROM (
SELECT row, rate, log10(rate) AS rate_log
FROM (
/* emulate the origin dataset */
SELECT data.1 row, data.2 rate
FROM (SELECT arrayJoin([
(1, 100), (2, 2), (3, 10), (4, 2)]) AS data))
ORDER BY row));
/*
┌─row─┬─rate─┬──────────────value─┬─rounded_value─┐
│ 1 │ 100 │ 100 │ 100 │
│ 2 │ 2 │ 49.99999999999999 │ 50 │
│ 3 │ 10 │ 4.999999999999999 │ 5 │
│ 4 │ 2 │ 2.4999999999999996 │ 2.5 │
└─────┴──────┴────────────────────┴───────────────┘
*/