Привет!
Если кратко, то мне нужна агрегатная функция sumMap, которая работает не для массивов, а для сгруппированных значений.
Но может быть и какой-то другой путь есть.
Есть табличка (app_id, name, point, value).
В один момент времени собирается несколько метрик.
Для некоторых метрик известны названия,
для некоторых - только шаблон названия.
Метрик в один момент собирается много, тысячи. И все они не нужны в ответе,
по этому выбрана такая схема, а не Nested.
Я хочу делать вычисления между метриками (не шаблонами), случившимися в один момент времени для заданного приложения.
Если бы названия метрик были извесны, то можно было бы применить комбинатор If,
но я знаю только шаблоны, а применять агрегационную функцию нужно в разрезе имени, а не шаблона.
CREATE TABLE metrics
(
app_id Int32,
name LowCardinality(String),
point DateTime,
value Float32
) ENGINE = MergeTree()
PRIMARY KEY (app_id, name, point)
select
point,
sumIf(value, name = 'X') as x,
array(groupArray(name)) as name_g,
array(groupArray(value)) as value_g,
sumMapForEach(name_g, value_g) -- не работает
from metrics
where
point between '2021-02-18 13:00:00' and '2021-02-18 13:30:00'
and app_id = 42
and (name = 'X' or name like 'a/%/b')
group by point
Я придумал костыль - обернул группы в дополнительный массив и применил комбинатор ForEach,
но это не работает.
Похоже, что мне нужна функция sumMap', такая, что sumMap'Array == sumMap.
Или может быть какой-нибудь способ развернуть строки в столбцы? 🙂
upd:
похоже, что так работает, только не понятно зачем делать группировку для sumMapForEach, она же теперь не агрегатная
select
point,
http,
sumMapForEach(name_g, value_g)
from (
select
point,
sumIf(value, name = 'X') as http,
array(groupArray(name)) as name_g,
array(groupArray(value)) as value_g
from metris
where
point between '2021-02-18 13:00:00' and '2021-02-18 13:30:00'
and app_id = 42
and (name = 'X' or name like 'a/%/b')
group by point
) as sub
group by point, http
upd2: вроде бы arrayReduce('sumMap', array(name_g), array(value_g)) работает