如何使用聚合组合器 ForEach + If

How to use aggregate combinators ForEach + If

在 ClickHouse 中,我可以更改聚合与组合器的工作方式。

ForEach 组合器聚合数组中每个元素的结果:

SELECT avgForEach(array)
FROM test

If 组合器可用于执行条件聚合:

SELECT avgIf(col, col > 0)
FROM test

但是如何将它们结合使用以在聚合值之前检查每个数组元素是否匹配某些条件?

我尝试使用 lambda 函数作为条件,但这没有用,例如:

SELECT avgForEachIf(array, x -> x > 0)
FROM test

如果组合器需要简单的表达式

你可以对 Null 使用技巧(聚合函数不考虑 Null)

SELECT avgForEach(arrayMap(x -> if(x > 0, x, NULL), a))
FROM
(
    SELECT [1, 2, 3, -5] AS a
    UNION ALL
    SELECT [1, 1, 1, 1]
)
┌─avgForEach(arrayMap(lambda(tuple(x), if(greater(x, 0), x, NULL)), a))─┐
│ [1,1.5,2,1]                                                           │
└───────────────────────────────────────────────────────────────────────┘

为了完整起见,一位同事指出我以错误的顺序使用了 ForEachIf 组合子。如果您在 If 前面添加,它将对每个数组元素进行评估。如果您附加 If 它将评估整个数组。

使用它,您可以创建一个包含布尔值的数组,指示每个元素是否与 IfForEach 组合器的条件匹配:

WITH arrayJoin([[1, 1], [-1, 2]]) AS A
SELECT avgIfForEach(A, arrayMap(x -> (x > 0), A))

┌─avgIfForEach(A, arrayMap(lambda(tuple(x), greater(x, 0)), A))─┐
│ [1,1.5]                                                       │
└───────────────────────────────────────────────────────────────┘